import unittest
from pathlib import Path
from tempfile import TemporaryDirectory

from mixersystem.data.repository import (
    update_frontmatter, parse_frontmatter, serialize_frontmatter,
)
from mixersystem.workflows.work.create_work import _upsert_build_status


class UpdateFrontmatterTest(unittest.TestCase):
    def test_stamp_on_fresh_file(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "plan.md"
            p.write_text("# Plan: Test\n\n## Summary\n\nDo the thing.\n")

            update_frontmatter(str(p), mock=False, provider="claude")

            text = p.read_text()
            self.assertTrue(text.startswith("---\n"))
            meta, body = parse_frontmatter(text)
            self.assertEqual(meta["mock"], "false")
            self.assertEqual(meta["provider"], "claude")
            self.assertIn("# Plan: Test", body)

    def test_bool_values_lowercase(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "work.md"
            p.write_text("# Work: Test\n")

            update_frontmatter(str(p), mock=True, verbose=False)

            meta, _ = parse_frontmatter(p.read_text())
            self.assertEqual(meta["mock"], "true")
            self.assertEqual(meta["verbose"], "false")

    def test_int_values(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "work.md"
            p.write_text("# Work: Test\n")

            update_frontmatter(str(p), max_test_iterations=5, branch_count=2)

            meta, _ = parse_frontmatter(p.read_text())
            self.assertEqual(meta["max_test_iterations"], "5")
            self.assertEqual(meta["branch_count"], "2")

    def test_idempotent_stamp(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "plan.md"
            p.write_text("# Plan: Test\n")

            update_frontmatter(str(p), provider="claude", mock=False)
            first = p.read_text()

            update_frontmatter(str(p), provider="claude", mock=False)
            second = p.read_text()

            self.assertEqual(first, second)

    def test_preserves_body(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "plan.md"
            body = "# Plan: Feature X\n\n## Summary\n\nBuild the feature.\n\n## Files\n\n- `a.py`\n"
            p.write_text(body)

            update_frontmatter(str(p), provider="gemini")

            _, result_body = parse_frontmatter(p.read_text())
            self.assertEqual(result_body, body)


class UpsertBuildStatusWithFrontmatterTest(unittest.TestCase):
    def test_preserves_frontmatter(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "work.md"
            p.write_text(
                "---\nmock: false\nmax_test_iterations: 5\n---\n\n"
                "# Work: Test\n\n## What Changed\n\n- `a.py` — added\n"
            )

            _upsert_build_status(
                work_path=str(p),
                build_succeeded=True,
                tests_succeeded=True,
                max_test_iterations=5,
                test_iterations=2,
                last_test_feedback="All good",
            )

            text = p.read_text()
            self.assertTrue(text.startswith("---\n"))
            meta, body = parse_frontmatter(text)
            self.assertEqual(meta["mock"], "false")
            self.assertEqual(meta["max_test_iterations"], "5")
            self.assertTrue(body.startswith("# Build Status\n"))
            self.assertIn("# Work: Test", body)

    def test_works_without_frontmatter(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "work.md"
            p.write_text("# Work: Test\n\n## What Changed\n\n- `a.py` — added\n")

            _upsert_build_status(
                work_path=str(p),
                build_succeeded=False,
                tests_succeeded=False,
                max_test_iterations=3,
                test_iterations=3,
                last_test_feedback="Still broken",
            )

            text = p.read_text()
            self.assertFalse(text.startswith("---\n"))
            self.assertTrue(text.startswith("# Build Status\n"))
            self.assertIn("build not succeeded", text)
            self.assertIn("# Work: Test", text)

    def test_replaces_existing_status_with_frontmatter(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "work.md"
            p.write_text(
                "---\nmock: true\n---\n\n"
                "# Build Status\n- build not succeeded\n- tests not succeeded\n\n"
                "# Work: Test\n"
            )

            _upsert_build_status(
                work_path=str(p),
                build_succeeded=True,
                tests_succeeded=True,
                max_test_iterations=5,
                test_iterations=4,
                last_test_feedback="",
            )

            text = p.read_text()
            meta, body = parse_frontmatter(text)
            self.assertEqual(meta["mock"], "true")
            self.assertIn("build succeeded", body)
            self.assertNotIn("build not succeeded", body)
            self.assertEqual(body.count("# Build Status"), 1)

    def test_works_on_missing_file(self) -> None:
        with TemporaryDirectory() as tmpdir:
            p = Path(tmpdir) / "work.md"

            _upsert_build_status(
                work_path=str(p),
                build_succeeded=False,
                tests_succeeded=False,
                max_test_iterations=1,
                test_iterations=1,
                last_test_feedback="no file",
            )

            text = p.read_text()
            self.assertTrue(text.startswith("# Build Status\n"))


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