from __future__ import annotations

import json
import tempfile
import unittest
from pathlib import Path

from us_cpa.cases import CaseConflictError, CaseManager


class CaseManagerTests(unittest.TestCase):
    def test_create_case_builds_expected_layout(self) -> None:
        with tempfile.TemporaryDirectory() as temp_dir:
            case_dir = Path(temp_dir) / "2025-jane-doe"
            manager = CaseManager(case_dir)

            manifest = manager.create_case(case_label="Jane Doe", tax_year=2025)

            self.assertEqual(manifest["caseLabel"], "Jane Doe")
            self.assertEqual(manifest["taxYear"], 2025)
            for name in (
                "input",
                "extracted",
                "return",
                "output",
                "reports",
                "issues",
                "sources",
            ):
                self.assertTrue((case_dir / name).is_dir())
            self.assertTrue((case_dir / "case-manifest.json").exists())

    def test_intake_registers_documents_and_user_facts(self) -> None:
        with tempfile.TemporaryDirectory() as temp_dir:
            root = Path(temp_dir)
            case_dir = root / "2025-jane-doe"
            document = root / "w2.txt"
            document.write_text("sample w2")
            manager = CaseManager(case_dir)
            manager.create_case(case_label="Jane Doe", tax_year=2025)

            result = manager.intake(
                tax_year=2025,
                user_facts={"filingStatus": "single", "taxpayer.ssnLast4": "1234"},
                document_paths=[document],
            )

            self.assertEqual(result["status"], "accepted")
            self.assertEqual(len(result["registeredDocuments"]), 1)
            self.assertTrue((case_dir / "input" / "w2.txt").exists())
            facts = json.loads((case_dir / "extracted" / "facts.json").read_text())
            self.assertEqual(facts["facts"]["filingStatus"]["value"], "single")

    def test_intake_extracts_machine_usable_facts_from_text_documents(self) -> None:
        with tempfile.TemporaryDirectory() as temp_dir:
            root = Path(temp_dir)
            case_dir = root / "2025-jane-doe"
            w2 = root / "w2.txt"
            w2.write_text(
                "Form W-2 Wage and Tax Statement\n"
                "Employee: Jane Doe\n"
                "Box 1 Wages, tips, other compensation 50000\n"
                "Box 2 Federal income tax withheld 6000\n"
            )
            interest = root / "1099-int.txt"
            interest.write_text(
                "Form 1099-INT\n"
                "Recipient: Jane Doe\n"
                "Box 1 Interest Income 1750\n"
            )
            manager = CaseManager(case_dir)
            manager.create_case(case_label="Jane Doe", tax_year=2025)

            result = manager.intake(
                tax_year=2025,
                user_facts={"filingStatus": "single"},
                document_paths=[w2, interest],
            )

            self.assertEqual(result["status"], "accepted")
            facts = json.loads((case_dir / "extracted" / "facts.json").read_text())
            self.assertEqual(facts["facts"]["wages"]["value"], 50000.0)
            self.assertEqual(facts["facts"]["federalWithholding"]["value"], 6000.0)
            self.assertEqual(facts["facts"]["taxableInterest"]["value"], 1750.0)
            self.assertEqual(facts["facts"]["wages"]["sources"][0]["sourceType"], "document_extract")

    def test_conflicting_facts_raise_structured_issue(self) -> None:
        with tempfile.TemporaryDirectory() as temp_dir:
            case_dir = Path(temp_dir) / "2025-jane-doe"
            manager = CaseManager(case_dir)
            manager.create_case(case_label="Jane Doe", tax_year=2025)
            manager.intake(
                tax_year=2025,
                user_facts={"filingStatus": "single"},
                document_paths=[],
            )

            with self.assertRaises(CaseConflictError) as context:
                manager.intake(
                    tax_year=2025,
                    user_facts={"filingStatus": "married_filing_jointly"},
                    document_paths=[],
                )

            issue = context.exception.issue
            self.assertEqual(issue["status"], "needs_resolution")
            self.assertEqual(issue["issueType"], "fact_conflict")
            self.assertEqual(issue["field"], "filingStatus")
            self.assertTrue((case_dir / "issues" / "open-issues.json").exists())


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