"""
Unit tests for server/fiscal_year_engine.py.

Run with: cd server && ../venv/bin/python3 -m unittest tests.test_fiscal_year_engine -v
"""
import os
import sys
import tempfile
import unittest

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))


class FiscalYearEngineTests(unittest.TestCase):
    def setUp(self):
        self._tmpdir = tempfile.mkdtemp()
        os.environ["CA_DATA_DIR"] = self._tmpdir
        for mod in ("db", "country_service", "fiscal_year_engine", "engines"):
            sys.modules.pop(mod, None)
        import db as db_mod
        import fiscal_year_engine as fye_mod
        global db, fye
        db, fye = db_mod, fye_mod
        db.init_db()

    def test_generate_periods_india_is_april_to_march(self):
        periods = fye.generate_periods("IN", 2025, count=1)
        self.assertEqual(periods, [("2025-26", "2025-04-01", "2026-03-31")])

    def test_generate_periods_uae_is_calendar_year(self):
        periods = fye.generate_periods("AE", 2026, count=1)
        self.assertEqual(periods, [("2026", "2026-01-01", "2026-12-31")])

    def test_unknown_country_raises_rather_than_guessing(self):
        with self.assertRaises(ValueError):
            fye.generate_periods("ZZ", 2026)

    def test_seed_default_periods_is_idempotent(self):
        fye.seed_default_periods("IN", around_year=2026, back=1, forward=1)
        first_count = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'IN'", one=True)["n"]
        fye.seed_default_periods("IN", around_year=2026, back=1, forward=1)
        second_count = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'IN'", one=True)["n"]
        self.assertEqual(first_count, second_count)

    def test_period_label_for_ad_falls_back_to_plain_ad_year_not_bs(self):
        # No periods configured at all for this country.
        label = fye.period_label_for_ad("AE", "2026-06-15", periods=[])
        self.assertEqual(label, "2026")  # not a Bikram Sambat label like '2083-84'

    def test_period_label_for_ad_uses_a_matching_configured_period(self):
        periods = [{"label": "2025-26", "start_ad": "2025-04-01", "end_ad": "2026-03-31"}]
        label = fye.period_label_for_ad("IN", "2025-12-25", periods=periods)
        self.assertEqual(label, "2025-26")

    def test_current_period_label_delegates_to_db_for_nepal_unchanged(self):
        # A Nepal firm (the default) must get exactly db.current_fy_label()'s
        # own behaviour — this module must never intercept or alter it.
        self.assertEqual(fye.current_period_label(1), db.current_fy_label())

    def test_current_period_label_resolves_indias_own_jurisdiction(self):
        fye.seed_default_periods("IN")
        db.execute("UPDATE firm SET country_code = 'IN' WHERE id = 1")
        label = fye.current_period_label(1)
        self.assertRegex(label, r"^\d{4}-\d{2}$")  # 'YYYY-YY' shape, not a BS label

    def test_sync_current_period_flags_exactly_one_row(self):
        fye.seed_default_periods("IN")
        current = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'IN' AND is_current = 1", one=True)["n"]
        self.assertEqual(current, 1)

    def test_loan_schedule_journals_grouped_by_ad_year_under_india_context_not_bs(self):
        import engines
        import country_service as cs
        fye.seed_default_periods("IN")
        with cs.use_country("IN"):
            result = engines.loan_schedule({
                "principal": 1000000, "annual_rate": 10, "tenure_periods": 12,
                "frequency": "monthly", "repayment": "emi", "start_date_ad": "2026-01-15",
            })
        keys = list(result.get("journals_by_fy", {}).keys())
        self.assertTrue(keys)
        for k in keys:
            self.assertRegex(k, r"^\d{4}-\d{2}$")  # e.g. '2025-26', never a BS label

    def test_loan_schedule_journals_stay_bs_labelled_under_nepal_context(self):
        import engines
        import country_service as cs
        with cs.use_country("NP"):
            result = engines.loan_schedule({
                "principal": 1000000, "annual_rate": 10, "tenure_periods": 12,
                "frequency": "monthly", "repayment": "emi", "start_date_ad": "2026-01-15",
            })
        keys = list(result.get("journals_by_fy", {}).keys())
        self.assertTrue(keys)
        for k in keys:
            self.assertTrue(int(k.split("-")[0]) > 2070)  # Bikram Sambat year range, unchanged


    def test_ensure_periods_exist_seeds_a_country_with_a_known_rule(self):
        count_before = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'AE'", one=True)["n"]
        self.assertEqual(count_before, 0)
        fye.ensure_periods_exist("AE")
        count_after = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'AE'", one=True)["n"]
        self.assertGreater(count_after, 0)

    def test_ensure_periods_exist_is_a_noop_for_a_country_with_no_rule(self):
        fye.ensure_periods_exist("ZZ")
        count = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'ZZ'", one=True)["n"]
        self.assertEqual(count, 0)

    def test_ensure_periods_exist_does_not_duplicate_on_a_second_call(self):
        fye.ensure_periods_exist("IN")
        first = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'IN'", one=True)["n"]
        fye.ensure_periods_exist("IN")
        second = db.query("SELECT COUNT(*) n FROM financial_period WHERE country_code = 'IN'", one=True)["n"]
        self.assertEqual(first, second)

    def test_financial_periods_for_firm_returns_nepals_own_table_unchanged(self):
        rows = fye.financial_periods_for_firm(1)
        expected = db.query("SELECT * FROM fiscal_year ORDER BY label_bs")
        self.assertEqual([dict(r) for r in rows], [dict(r) for r in expected])

    def test_financial_periods_for_firm_auto_seeds_and_uses_the_label_bs_key_for_uae(self):
        db.execute("UPDATE firm SET country_code = 'AE' WHERE id = 1")
        rows = fye.financial_periods_for_firm(1)
        self.assertTrue(rows)
        for r in rows:
            # Same key name every existing FY picker/pro-ration lookup
            # already reads (label_bs) even though this is a plain calendar
            # year, not Bikram Sambat — see the function's own docstring.
            self.assertIn("label_bs", r.keys())
            self.assertRegex(r["label_bs"], r"^\d{4}$")

    def test_financial_periods_for_firm_uses_apr_mar_labels_for_india(self):
        db.execute("UPDATE firm SET country_code = 'IN' WHERE id = 1")
        rows = fye.financial_periods_for_firm(1)
        self.assertTrue(rows)
        for r in rows:
            self.assertRegex(r["label_bs"], r"^\d{4}-\d{2}$")

    def test_financial_periods_for_firm_flags_exactly_one_current_period_for_uae(self):
        db.execute("UPDATE firm SET country_code = 'AE' WHERE id = 1")
        rows = fye.financial_periods_for_firm(1)
        current = [r for r in rows if r["is_current"]]
        self.assertEqual(len(current), 1)


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