# -*- coding: utf-8 -*-
"""STEP 5 tests — mandatory disclosure (Rule 12.285).

    odoo -d <db> -u activeblue_familylaw --test-enable \
         --test-tags familylaw_step5 --stop-after-init

Proves:
  * form selection 12.902(b) vs 12.902(c) by gross annual income (threshold);
  * 45-day affidavit due date with weekend roll (fixed dates);
  * mandatory disclosure cannot be waived; non-mandatory can;
  * line-item totals and net worth;
  * per-proceeding isolation + seeding.
"""

from datetime import date

from odoo.tests.common import TransactionCase, tagged
from odoo.exceptions import UserError


@tagged("post_install", "-at_install", "familylaw", "familylaw_step5")
class TestStep5Disclosure(TransactionCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.partner = cls.env["res.partner"].create({"name": "Disc Client"})
        cls.case = cls.env["familylaw.case"].create({
            "name": "Disclosure Matter",
            "client_id": cls.partner.id,
            "case_type": "dissolution_children",
        })
        cls.proc = cls.case.proceeding_ids[0]
        cls.Aff = cls.env["familylaw.financial.affidavit"]
        cls.Item = cls.env["familylaw.disclosure.item"]

    def _aff(self, income, **kw):
        vals = {
            "proceeding_id": self.proc.id,
            "name": "Affiant",
            "gross_annual_income": income,
        }
        vals.update(kw)
        return self.Aff.create(vals)

    # --- form selection by income -------------------------------------------
    def test_01_low_income_short_form(self):
        aff = self._aff(30000.0)
        self.assertEqual(aff.form_type, "short")
        self.assertEqual(aff.form_reference, "12.902(b)")

    def test_02_high_income_long_form(self):
        aff = self._aff(80000.0)
        self.assertEqual(aff.form_type, "long")
        self.assertEqual(aff.form_reference, "12.902(c)")

    def test_03_threshold_is_long_form(self):
        # exactly at threshold (>=) -> long form
        aff = self._aff(50000.0)
        self.assertEqual(aff.form_type, "long")

    def test_04_just_below_threshold_short(self):
        aff = self._aff(49999.0)
        self.assertEqual(aff.form_type, "short")

    def test_05_form_recomputes_on_income_change(self):
        aff = self._aff(10000.0)
        self.assertEqual(aff.form_type, "short")
        aff.gross_annual_income = 120000.0
        self.assertEqual(aff.form_type, "long")

    # --- 45-day due date ----------------------------------------------------
    def test_06_due_date_45_days(self):
        # 2025-01-01 + 45 = 2025-02-15 (Sat) -> 2025-02-17 (Mon)
        aff = self._aff(20000.0, trigger_date=date(2025, 1, 1))
        self.assertEqual(aff.due_date, date(2025, 2, 17))

    def test_07_due_date_no_weekend_roll(self):
        # 2025-02-03 (Mon) + 45 = 2025-03-20 (Thu)
        aff = self._aff(20000.0, trigger_date=date(2025, 2, 3))
        self.assertEqual(aff.due_date, date(2025, 3, 20))

    def test_08_no_trigger_no_due(self):
        aff = self._aff(20000.0)
        self.assertFalse(aff.due_date)

    # --- can't waive mandatory ----------------------------------------------
    def test_09_mandatory_cannot_waive(self):
        item = self.Item.create({
            "proceeding_id": self.proc.id,
            "name": "Tax returns",
            "is_mandatory": True,
        })
        with self.assertRaises(UserError):
            item.action_waive()
        self.assertEqual(item.state, "required")

    def test_10_non_mandatory_can_waive(self):
        item = self.Item.create({
            "proceeding_id": self.proc.id,
            "name": "Optional extra",
            "is_mandatory": False,
        })
        item.action_waive()
        self.assertEqual(item.state, "waived")

    def test_11_mark_provided(self):
        item = self.Item.create({
            "proceeding_id": self.proc.id,
            "name": "Pay stubs",
            "is_mandatory": True,
        })
        item.action_mark_provided()
        self.assertEqual(item.state, "provided")

    # --- totals -------------------------------------------------------------
    def test_12_totals_and_net_worth(self):
        aff = self._aff(60000.0)
        self.env["familylaw.fin.line"].create([
            {"affidavit_id": aff.id, "category": "income", "name": "Salary", "amount": 5000.0},
            {"affidavit_id": aff.id, "category": "expense", "name": "Rent", "amount": 2000.0},
            {"affidavit_id": aff.id, "category": "asset", "name": "Home", "amount": 300000.0},
            {"affidavit_id": aff.id, "category": "liability", "name": "Mortgage", "amount": 180000.0},
        ])
        self.assertEqual(aff.total_income, 5000.0)
        self.assertEqual(aff.total_expense, 2000.0)
        self.assertEqual(aff.total_asset, 300000.0)
        self.assertEqual(aff.total_liability, 180000.0)
        self.assertEqual(aff.net_worth, 120000.0)

    # --- seeding + isolation ------------------------------------------------
    def test_13_seed_disclosure_checklist(self):
        self.proc.action_seed_disclosure_items()
        self.assertTrue(self.proc.disclosure_item_ids)
        self.assertTrue(all(self.proc.disclosure_item_ids.mapped("is_mandatory")))

    def test_14_seed_is_idempotent(self):
        self.proc.action_seed_disclosure_items()
        n1 = len(self.proc.disclosure_item_ids)
        self.proc.action_seed_disclosure_items()
        self.assertEqual(len(self.proc.disclosure_item_ids), n1)

    def test_15_affidavit_isolated_per_proceeding(self):
        proc2 = self.env["familylaw.proceeding"].create({
            "case_id": self.case.id,
            "name": "Second",
            "proceeding_type": "modification",
        })
        a1 = self._aff(20000.0)
        a2 = self.Aff.create({
            "proceeding_id": proc2.id, "name": "Other", "gross_annual_income": 90000.0,
        })
        self.assertIn(a1, self.proc.affidavit_ids)
        self.assertNotIn(a2, self.proc.affidavit_ids)
