from __future__ import annotations

import json
import os
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
FIX_IN = ROOT / "tests" / "fixtures" / "in"


def run_cli(args: list[str], env: dict[str, str]) -> subprocess.CompletedProcess[str]:
    return subprocess.run(
        [sys.executable, "-m", "doc2md.cli", *args],
        cwd=ROOT,
        text=True,
        capture_output=True,
        env=env,
    )


class HistoryCommandTest(unittest.TestCase):
    def test_history_search_rerun_json(self) -> None:
        input_path = FIX_IN / "sample.csv"
        output_path = ROOT / "docs_out" / "sample.csv.md"
        if output_path.exists():
            output_path.unlink()

        with tempfile.TemporaryDirectory() as tmpdir:
            db_path = Path(tmpdir) / "history.db"
            env = os.environ.copy()
            env["DOC2MD_HISTORY_DB"] = str(db_path)

            convert = run_cli([str(input_path), "--quiet", "--yes"], env)
            self.assertEqual(convert.returncode, 0)

            history = run_cli(["history", "--json"], env)
            self.assertEqual(history.returncode, 0)
            runs = json.loads(history.stdout)
            self.assertEqual(len(runs), 1)
            run_id = runs[0]["id"]

            search = run_cli(["search", "sample.csv", "--json"], env)
            self.assertEqual(search.returncode, 0)
            results = json.loads(search.stdout)
            self.assertEqual(results[0]["id"], run_id)

            rerun = run_cli(["rerun", str(run_id), "--json"], env)
            self.assertEqual(rerun.returncode, 0)
            rerun_result = json.loads(rerun.stdout)
            self.assertEqual(rerun_result["rerun_of"], run_id)
            self.assertEqual(rerun_result["exit_code"], 0)
            self.assertTrue(output_path.exists())

            history_after = run_cli(["history", "--json"], env)
            runs_after = json.loads(history_after.stdout)
            self.assertEqual(len(runs_after), 2)

        if output_path.exists():
            output_path.unlink()

    def test_history_prune_keep_one(self) -> None:
        input_path = FIX_IN / "sample.csv"
        with tempfile.TemporaryDirectory() as tmpdir:
            db_path = Path(tmpdir) / "history.db"
            out1 = Path(tmpdir) / "out1.md"
            out2 = Path(tmpdir) / "out2.md"
            env = os.environ.copy()
            env["DOC2MD_HISTORY_DB"] = str(db_path)

            first = run_cli([str(input_path), "-o", str(out1), "--quiet"], env)
            second = run_cli([str(input_path), "-o", str(out2), "--quiet"], env)
            self.assertEqual(first.returncode, 0)
            self.assertEqual(second.returncode, 0)

            history_before = run_cli(["history", "--json"], env)
            self.assertEqual(history_before.returncode, 0)
            runs_before = json.loads(history_before.stdout)
            self.assertEqual(len(runs_before), 2)

            prune = run_cli(["history", "prune", "--keep", "1", "--json"], env)
            self.assertEqual(prune.returncode, 0)
            result = json.loads(prune.stdout)
            self.assertEqual(result["deleted"], 1)
            self.assertEqual(result["remaining"], 1)

            history_after = run_cli(["history", "--json"], env)
            runs_after = json.loads(history_after.stdout)
            self.assertEqual(len(runs_after), 1)

    def test_search_rerun_top_match(self) -> None:
        input_path = FIX_IN / "sample.csv"
        with tempfile.TemporaryDirectory() as tmpdir:
            db_path = Path(tmpdir) / "history.db"
            out1 = Path(tmpdir) / "out1.md"
            out2 = Path(tmpdir) / "out2.md"
            env = os.environ.copy()
            env["DOC2MD_HISTORY_DB"] = str(db_path)

            run_cli([str(input_path), "-o", str(out1), "--quiet", "--yes"], env)
            run_cli([str(input_path), "-o", str(out2), "--quiet", "--yes"], env)

            history = run_cli(["history", "--json"], env)
            runs = json.loads(history.stdout)
            top_id = runs[0]["id"]

            result = run_cli(["search", "sample.csv", "--rerun", "--json"], env)
            self.assertEqual(result.returncode, 0)
            payload = json.loads(result.stdout)
            self.assertEqual(payload["rerun_of"], top_id)
            self.assertEqual(payload["exit_code"], 0)

            missing = run_cli(["search", "nope", "--rerun"], env)
            self.assertEqual(missing.returncode, 2)
            self.assertIn("No matching runs", missing.stderr)


if __name__ == "__main__":
    unittest.main()
