"""CLI coverage tests v3: filing, tenant, db, analytics, dispatch."""

from __future__ import annotations

import json
import sys
from pathlib import Path
from unittest import mock

import pytest

from orxaq.experiences import cli as cli_mod
from orxaq.experiences.cli import main

# ── Filing generate (lines 2206-2231) ────────────────────────


class TestFilingGenerate:
    def _mock_filing_result(self, tmp_path):
        """Create a mock FilingResult."""
        result = mock.MagicMock()
        result.output_dir = str(tmp_path)
        result.institution_id = "BANK001"
        result.period = "2026Q1"
        result.duration_seconds = 1.5
        result.audit_entries_count = 10
        result.files = ["f1.json", "f2.csv"]
        return result

    def test_filing_generate_json(self, tmp_path: Path, capsys: pytest.CaptureFixture) -> None:
        result = self._mock_filing_result(tmp_path)
        mock_gen = mock.MagicMock()
        mock_gen.return_value.generate.return_value = result
        mock_cfg = mock.MagicMock()

        filing_mod = mock.MagicMock()
        filing_mod.FilingConfig = mock_cfg
        filing_mod.FilingGenerator = mock_gen

        with mock.patch.dict("sys.modules", {"orxaq.credit.filing": filing_mod}):
            rc = main(
                ["--json", "filing", "generate", "--output", str(tmp_path), "--n-samples", "50"]
            )
        assert rc == 0
        data = json.loads(capsys.readouterr().out)
        assert data["institution_id"] == "BANK001"
        assert "files" in data

    def test_filing_generate_text(self, tmp_path: Path, capsys: pytest.CaptureFixture) -> None:
        result = self._mock_filing_result(tmp_path)
        mock_gen = mock.MagicMock()
        mock_gen.return_value.generate.return_value = result
        mock_cfg = mock.MagicMock()

        filing_mod = mock.MagicMock()
        filing_mod.FilingConfig = mock_cfg
        filing_mod.FilingGenerator = mock_gen

        with mock.patch.dict("sys.modules", {"orxaq.credit.filing": filing_mod}):
            rc = main(["filing", "generate", "--output", str(tmp_path), "--n-samples", "50"])
        assert rc == 0
        out = capsys.readouterr().out
        assert "Filing generated" in out
        assert "BANK001" in out


# ── Tenant list non-empty text (lines 2858-2861) ─────────────


class TestTenantListNonEmpty:
    def test_tenant_list_text_nonempty(self, capsys: pytest.CaptureFixture) -> None:
        from orxaq.enterprise.tenant import TenantContext

        fake_ctx = TenantContext(
            tenant_id="t1",
            name="Acme",
            tier="pro",
            max_entities=1000,
            max_edges=5000,
        )
        with mock.patch(
            "orxaq.enterprise.tenant.TenantStore.list_tenants",
            return_value=[fake_ctx],
        ):
            rc = main(["tenant", "list"])
        assert rc == 0
        out = capsys.readouterr().out
        assert "t1" in out
        assert "Acme" in out


# ── Tenant get (lines 2872-2889) ─────────────────────────────


class TestTenantGet:
    def test_tenant_get_json(self, capsys: pytest.CaptureFixture) -> None:
        from orxaq.enterprise.tenant import TenantContext

        fake_ctx = TenantContext(
            tenant_id="get-test",
            name="Get Test",
            tier="free",
            max_entities=100,
            max_edges=500,
        )
        with mock.patch(
            "orxaq.enterprise.tenant.TenantStore.get",
            return_value=fake_ctx,
        ):
            rc = main(["--json", "tenant", "get", "get-test"])
        assert rc == 0
        data = json.loads(capsys.readouterr().out)
        assert data["tenant_id"] == "get-test"
        assert data["name"] == "Get Test"

    def test_tenant_get_text(self, capsys: pytest.CaptureFixture) -> None:
        from orxaq.enterprise.tenant import TenantContext

        fake_ctx = TenantContext(
            tenant_id="get-text",
            name="Text Test",
            tier="pro",
            max_entities=200,
            max_edges=1000,
        )
        with mock.patch(
            "orxaq.enterprise.tenant.TenantStore.get",
            return_value=fake_ctx,
        ):
            rc = main(["tenant", "get", "get-text"])
        assert rc == 0
        out = capsys.readouterr().out
        assert "get-text" in out
        assert "Text Test" in out
        assert "Tier:" in out

    def test_tenant_get_not_found(self, capsys: pytest.CaptureFixture) -> None:
        rc = main(["tenant", "get", "nonexistent-tenant-xyz"])
        assert rc == 1
        out = capsys.readouterr().out
        assert "not found" in out.lower()


# ── Tenant delete (lines 2897-2898) ──────────────────────────


class TestTenantDelete:
    def test_tenant_delete_success(self, capsys: pytest.CaptureFixture) -> None:
        with mock.patch(
            "orxaq.enterprise.tenant.TenantStore.delete",
            return_value=True,
        ):
            rc = main(["tenant", "delete", "del-test"])
        assert rc == 0
        out = capsys.readouterr().out
        assert "Deleted" in out

    def test_tenant_delete_not_found(self, capsys: pytest.CaptureFixture) -> None:
        main(["tenant", "delete", "nonexistent-xyz"])
        out = capsys.readouterr().out
        assert "not found" in out.lower() or "Not found" in out


# ── DB events non-empty (lines 1935-1939) ────────────────────


class TestDbEventsNonEmpty:
    def test_db_events_text_with_data(self, tmp_path: Path, capsys: pytest.CaptureFixture) -> None:
        from orxaq.fabric.persistence import SQLiteStore

        db = str(tmp_path / "test.db")
        with SQLiteStore(db) as store:
            store.log_event("test.event", "alice", "something happened")
        rc = main(["db", "--db", db, "events"])
        assert rc == 0
        out = capsys.readouterr().out
        assert "Audit Events" in out
        assert "test.event" in out
        assert "alice" in out


# ── Metrics recent non-empty (lines 1667-1671) ───────────────


class TestMetricsRecentNonEmpty:
    def test_metrics_recent_text_with_tasks(self, capsys: pytest.CaptureFixture) -> None:
        from orxaq.orchestration.metrics import MetricsCollector

        fake_tasks = [
            {
                "task_id": "task-001",
                "status": "completed",
                "duration_ms": 123.4,
                "cost_usd": 0.0012,
            }
        ]
        with mock.patch.object(MetricsCollector, "recent_tasks", return_value=fake_tasks):
            rc = main(["metrics", "recent"])
        assert rc == 0
        out = capsys.readouterr().out
        assert "Recent Tasks" in out
        assert "task-001" in out


# ── Analytics empty paths (lines 2016-2017, 2041, 2043-2044, 2088-2089, 2106) ──


class TestAnalyticsEmptyPaths:
    @pytest.fixture(autouse=True)
    def _empty_db(self, tmp_path, monkeypatch):
        db_file = tmp_path / "empty.db"
        from orxaq.fabric.persistence import SQLiteStore

        SQLiteStore(str(db_file)).close()
        monkeypatch.setattr(cli_mod, "_get_db_path", lambda _args: str(db_file))

    def test_query_events_empty_text(self, capsys) -> None:
        with mock.patch.object(sys, "argv", ["orxaq", "analytics", "query-events"]):
            rc = cli_mod.main()
        assert rc == 0
        out = capsys.readouterr().out
        assert "No events" in out

    def test_query_snapshots_empty_json(self, capsys) -> None:
        with mock.patch.object(sys, "argv", ["orxaq", "--json", "analytics", "query-snapshots"]):
            rc = cli_mod.main()
        assert rc == 0
        data = json.loads(capsys.readouterr().out)
        assert data["count"] == 0

    def test_query_snapshots_empty_text(self, capsys) -> None:
        with mock.patch.object(sys, "argv", ["orxaq", "analytics", "query-snapshots"]):
            rc = cli_mod.main()
        assert rc == 0
        out = capsys.readouterr().out
        assert "No snapshots" in out

    def test_timeline_empty_text(self, capsys) -> None:
        with mock.patch.object(sys, "argv", ["orxaq", "analytics", "timeline"]):
            rc = cli_mod.main()
        assert rc == 0
        out = capsys.readouterr().out
        assert "No data" in out

    def test_search_json(self, capsys) -> None:
        with mock.patch.object(sys, "argv", ["orxaq", "--json", "analytics", "search", "test"]):
            rc = cli_mod.main()
        assert rc == 0
        data = json.loads(capsys.readouterr().out)
        assert data["count"] == 0


# ── Dispatch fallthrough (lines 3091-3116) ────────────────────


class TestDispatchFallthrough:
    def test_filing_no_subcommand(self, capsys) -> None:
        with pytest.raises(SystemExit):
            main(["filing"])

    def test_stream_no_subcommand(self, capsys) -> None:
        with pytest.raises(SystemExit):
            main(["stream"])

    def test_analytics_no_subcommand(self, capsys) -> None:
        with pytest.raises(SystemExit):
            main(["analytics"])

    def test_metrics_no_subcommand(self, capsys) -> None:
        with pytest.raises(SystemExit):
            main(["metrics"])

    def test_db_no_subcommand(self, capsys) -> None:
        with pytest.raises(SystemExit):
            main(["db"])
