from __future__ import annotations

import json
import tempfile
import unittest
from io import BytesIO
from pathlib import Path

from reportlab.pdfgen import canvas

from us_cpa.cases import CaseManager
from us_cpa.prepare import EfileExporter, PrepareEngine
from us_cpa.sources import TaxYearCorpus, bootstrap_irs_catalog


class PrepareEngineTests(unittest.TestCase):
    def build_case(self, temp_dir: str) -> tuple[CaseManager, TaxYearCorpus]:
        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={
                "taxpayer.fullName": "Jane Doe",
                "filingStatus": "single",
                "wages": 50000,
                "taxableInterest": 100,
                "federalWithholding": 6000,
            },
            document_paths=[],
        )

        corpus = TaxYearCorpus(cache_root=Path(temp_dir) / "cache")

        def fake_fetch(url: str) -> bytes:
            buffer = BytesIO()
            pdf = canvas.Canvas(buffer)
            pdf.drawString(72, 720, f"Template for {url}")
            pdf.save()
            return buffer.getvalue()

        corpus.download_catalog(2025, bootstrap_irs_catalog(2025), fetcher=fake_fetch)
        return manager, corpus

    def test_prepare_creates_normalized_return_and_artifacts(self) -> None:
        with tempfile.TemporaryDirectory() as temp_dir:
            manager, corpus = self.build_case(temp_dir)
            engine = PrepareEngine(corpus=corpus)

            result = engine.prepare_case(manager.case_dir)

            self.assertEqual(result["status"], "prepared")
            self.assertEqual(result["summary"]["requiredForms"], ["f1040"])
            self.assertEqual(result["summary"]["reviewRequiredArtifacts"], ["f1040"])
            self.assertTrue((manager.case_dir / "return" / "normalized-return.json").exists())
            self.assertTrue((manager.case_dir / "output" / "artifacts.json").exists())
            normalized = json.loads((manager.case_dir / "return" / "normalized-return.json").read_text())
            self.assertEqual(normalized["totals"]["adjustedGrossIncome"], 50100.0)
            self.assertEqual(normalized["totals"]["taxableIncome"], 34350.0)

    def test_exporter_writes_efile_ready_payload(self) -> None:
        with tempfile.TemporaryDirectory() as temp_dir:
            manager, corpus = self.build_case(temp_dir)
            engine = PrepareEngine(corpus=corpus)
            engine.prepare_case(manager.case_dir)

            export = EfileExporter().export_case(manager.case_dir)

            self.assertEqual(export["status"], "draft")
            self.assertTrue((manager.case_dir / "output" / "efile-ready.json").exists())
            self.assertEqual(export["returnSummary"]["requiredForms"], ["f1040"])


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