"""
Integration tests for prompt CLI commands.

Tests Click CLI commands with CliRunner and a real SQLite database.
"""

import json
import pytest
import tempfile
from pathlib import Path

from click.testing import CliRunner

from markitect.prompts.cli import prompt_commands
from markitect.prompts.dependencies.models import DependencyEdge, EdgeType
from markitect.prompts.dependencies.repository import SQLiteDependencyRepository
from markitect.prompts.models import Artifact, ArtifactType
from markitect.prompts.repositories.sqlite import SQLiteArtifactRepository


@pytest.fixture
def temp_db():
    """Create temporary database for testing."""
    with tempfile.NamedTemporaryFile(suffix=".db", delete=False) as f:
        db_path = f.name
    yield db_path
    Path(db_path).unlink(missing_ok=True)


@pytest.fixture
def runner():
    """Click CLI test runner."""
    return CliRunner()


@pytest.fixture
def seeded_db(temp_db):
    """Seed database with test data and return path."""
    art_repo = SQLiteArtifactRepository(temp_db)
    dep_repo = SQLiteDependencyRepository(temp_db)

    a = Artifact.create(space_id="s", name="a", content="content-a",
                        artifact_type=ArtifactType.CONTENT)
    b = Artifact.create(space_id="s", name="b", content="content-b",
                        artifact_type=ArtifactType.CONTENT)
    a = art_repo.create(a)
    b = art_repo.create(b)

    edge = DependencyEdge.create(
        source_artifact_id=a.id,
        target_artifact_id=b.id,
        run_id="run-1",
        edge_type=EdgeType.REQUIRES,
    )
    dep_repo.create(edge)

    return temp_db, a.id, b.id


class TestTraceCommand:
    """Tests for the 'trace' command."""

    def test_trace_existing_artifact(self, runner, seeded_db):
        """Test tracing an existing artifact."""
        db_path, art_a, art_b = seeded_db
        result = runner.invoke(
            prompt_commands, ["trace", art_a, "--database", db_path]
        )
        assert result.exit_code == 0
        data = json.loads(result.output)
        assert data["artifact_id"] == art_a

    def test_trace_nonexistent_artifact(self, runner, temp_db):
        """Test tracing a non-existent artifact."""
        # Initialize tables
        SQLiteArtifactRepository(temp_db)
        SQLiteDependencyRepository(temp_db)

        result = runner.invoke(
            prompt_commands, ["trace", "nonexistent", "--database", temp_db]
        )
        assert result.exit_code != 0


class TestGraphCommand:
    """Tests for the 'graph' command."""

    def test_graph_mermaid(self, runner, seeded_db):
        """Test graph export in mermaid format."""
        db_path, art_a, _ = seeded_db
        result = runner.invoke(
            prompt_commands,
            ["graph", art_a, "--format", "mermaid", "--database", db_path],
        )
        assert result.exit_code == 0
        assert "graph LR" in result.output

    def test_graph_dot(self, runner, seeded_db):
        """Test graph export in DOT format."""
        db_path, art_a, _ = seeded_db
        result = runner.invoke(
            prompt_commands,
            ["graph", art_a, "--format", "dot", "--database", db_path],
        )
        assert result.exit_code == 0
        assert "digraph" in result.output


class TestRunsCommand:
    """Tests for the 'runs' command."""

    def test_runs_empty(self, runner, seeded_db):
        """Test listing runs when none are registered."""
        db_path, _, _ = seeded_db
        result = runner.invoke(
            prompt_commands, ["runs", "--database", db_path]
        )
        assert result.exit_code == 0
        assert "No runs found" in result.output

    def test_runs_with_limit(self, runner, seeded_db):
        """Test listing runs with limit option."""
        db_path, _, _ = seeded_db
        result = runner.invoke(
            prompt_commands, ["runs", "--limit", "5", "--database", db_path]
        )
        assert result.exit_code == 0


class TestDebtCommand:
    """Tests for the 'debt' command."""

    def test_debt_no_stale(self, runner, seeded_db):
        """Test debt when no stale artifacts exist."""
        db_path, _, _ = seeded_db
        result = runner.invoke(
            prompt_commands, ["debt", "--database", db_path]
        )
        assert result.exit_code == 0
        assert "No stale artifacts" in result.output

    def test_debt_for_artifact(self, runner, seeded_db):
        """Test debt for a specific artifact."""
        db_path, art_a, _ = seeded_db
        result = runner.invoke(
            prompt_commands,
            ["debt", "--artifact", art_a, "--database", db_path],
        )
        assert result.exit_code == 0
        assert "No impact debt" in result.output


class TestStatsCommand:
    """Tests for the 'stats' command."""

    def test_stats_with_data(self, runner, seeded_db):
        """Test stats with real graph data."""
        db_path, _, _ = seeded_db
        result = runner.invoke(
            prompt_commands, ["stats", "--database", db_path]
        )
        assert result.exit_code == 0
        data = json.loads(result.output)
        assert data["total_nodes"] == 2
        assert data["total_edges"] == 1
        assert data["has_cycles"] is False

    def test_stats_empty_db(self, runner, temp_db):
        """Test stats on empty database."""
        SQLiteArtifactRepository(temp_db)
        SQLiteDependencyRepository(temp_db)

        result = runner.invoke(
            prompt_commands, ["stats", "--database", temp_db]
        )
        assert result.exit_code == 0
        data = json.loads(result.output)
        assert data["total_nodes"] == 0
        assert data["total_edges"] == 0
