from __future__ import annotations

import unittest

from us_cpa.returns import normalize_case_facts, resolve_required_forms, tax_on_ordinary_income


class ReturnModelTests(unittest.TestCase):
    def test_normalize_case_facts_computes_basic_1040_totals(self) -> None:
        normalized = normalize_case_facts(
            {
                "taxpayer.fullName": "Jane Doe",
                "filingStatus": "single",
                "wages": 50000,
                "taxableInterest": 100,
                "federalWithholding": 6000,
            },
            2025,
        )

        self.assertEqual(normalized["requiredForms"], ["f1040"])
        self.assertEqual(normalized["deductions"]["standardDeduction"], 15750.0)
        self.assertEqual(normalized["totals"]["adjustedGrossIncome"], 50100.0)
        self.assertEqual(normalized["totals"]["taxableIncome"], 34350.0)
        self.assertEqual(normalized["totals"]["refund"], 2116.5)

    def test_resolve_required_forms_adds_business_and_interest_forms(self) -> None:
        normalized = normalize_case_facts(
            {
                "filingStatus": "single",
                "wages": 0,
                "taxableInterest": 2000,
                "businessIncome": 12000,
            },
            2025,
        )

        self.assertEqual(
            resolve_required_forms(normalized),
            ["f1040", "f1040sb", "f1040sc", "f1040sse", "f1040s1", "f8995"],
        )

    def test_tax_bracket_calculation_uses_2025_single_rates(self) -> None:
        self.assertEqual(tax_on_ordinary_income(34350.0, "single", 2025), 3883.5)

    def test_tax_bracket_calculation_uses_selected_tax_year(self) -> None:
        self.assertEqual(tax_on_ordinary_income(33650.0, "single", 2024), 3806.0)

    def test_normalize_case_facts_rejects_unsupported_tax_year(self) -> None:
        with self.assertRaisesRegex(ValueError, "Unsupported tax year"):
            normalize_case_facts({"filingStatus": "single"}, 2023)

    def test_normalize_case_facts_preserves_provenance_and_expands_form_resolution(self) -> None:
        normalized = normalize_case_facts(
            {
                "taxpayer.fullName": "Jane Doe",
                "spouse.fullName": "John Doe",
                "dependents": [{"fullName": "Kid Doe", "ssnLast4": "4321"}],
                "filingStatus": "married_filing_jointly",
                "wages": 50000,
                "taxableInterest": 2001,
                "capitalGainLoss": 400,
                "rentalIncome": 1200,
                "itemizedDeductions": 40000,
                "hsaContribution": 1000,
                "educationCredit": 500,
                "foreignTaxCredit": 250,
                "qualifiedBusinessIncome": 12000,
                "traditionalIraBasis": 6000,
                "additionalMedicareTax": 100,
                "netInvestmentIncomeTax": 200,
                "alternativeMinimumTax": 300,
                "additionalTaxPenalty": 50,
                "energyCredit": 600,
                "_factMetadata": {
                    "wages": {"sources": [{"sourceType": "document_extract", "documentName": "w2.txt"}]},
                },
            },
            2025,
        )

        self.assertEqual(normalized["spouse"]["fullName"], "John Doe")
        self.assertEqual(normalized["dependents"][0]["fullName"], "Kid Doe")
        self.assertEqual(normalized["provenance"]["income.wages"]["sources"][0]["documentName"], "w2.txt")
        self.assertIn("f1040sa", normalized["requiredForms"])
        self.assertIn("f1040sd", normalized["requiredForms"])
        self.assertIn("f8949", normalized["requiredForms"])
        self.assertIn("f1040se", normalized["requiredForms"])
        self.assertIn("f8889", normalized["requiredForms"])
        self.assertIn("f8863", normalized["requiredForms"])
        self.assertIn("f1116", normalized["requiredForms"])
        self.assertIn("f8995", normalized["requiredForms"])
        self.assertIn("f8606", normalized["requiredForms"])
        self.assertIn("f8959", normalized["requiredForms"])
        self.assertIn("f8960", normalized["requiredForms"])
        self.assertIn("f6251", normalized["requiredForms"])
        self.assertIn("f5329", normalized["requiredForms"])
        self.assertIn("f5695", normalized["requiredForms"])


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