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

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

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import ipo_engines as ie  # noqa: E402


class RestatementAnalysisTests(unittest.TestCase):
    def test_variance_and_pct(self):
        out = ie.restatement_analysis([
            {"id": 1, "fy_label": "2080-81", "account": "Revenue", "previously_reported": 1000000, "restated": 950000},
        ])
        self.assertEqual(out["rows"][0]["variance"], -50000.0)
        self.assertEqual(out["rows"][0]["variance_pct"], -5.0)
        self.assertEqual(out["total_absolute_impact"], 50000.0)

    def test_impact_grouped_by_fy(self):
        out = ie.restatement_analysis([
            {"fy_label": "2080-81", "account": "A", "previously_reported": 100, "restated": 90},
            {"fy_label": "2080-81", "account": "B", "previously_reported": 200, "restated": 220},
            {"fy_label": "2081-82", "account": "C", "previously_reported": 50, "restated": 40},
        ])
        self.assertEqual(out["impact_by_fy"]["2080-81"], 10.0)
        self.assertEqual(out["impact_by_fy"]["2081-82"], -10.0)

    def test_zero_previously_reported_no_pct(self):
        out = ie.restatement_analysis([{"fy_label": "X", "account": "A", "previously_reported": 0, "restated": 100}])
        self.assertIsNone(out["rows"][0]["variance_pct"])

    def test_empty_no_crash(self):
        out = ie.restatement_analysis([])
        self.assertEqual(out["lines_restated"], 0)
        self.assertEqual(out["total_absolute_impact"], 0.0)


class WorkingCapitalAdequacyTests(unittest.TestCase):
    def test_shortfall_detected(self):
        out = ie.working_capital_adequacy([
            {"period_label": "FY1", "projected_requirement": 5000000, "available_from_operations": 3000000, "ipo_proceeds_allocated": 1000000},
        ])
        self.assertFalse(out["overall_adequate"])
        self.assertEqual(out["shortfall_periods"], 1)
        self.assertEqual(out["rows"][0]["gap"], 1000000.0)

    def test_adequate_when_covered(self):
        out = ie.working_capital_adequacy([
            {"period_label": "FY1", "projected_requirement": 4000000, "available_from_operations": 3000000, "ipo_proceeds_allocated": 1000000},
        ])
        self.assertTrue(out["overall_adequate"])
        self.assertTrue(out["rows"][0]["adequate"])

    def test_cumulative_gap_across_periods(self):
        out = ie.working_capital_adequacy([
            {"period_label": "FY1", "projected_requirement": 5000000, "available_from_operations": 4000000, "ipo_proceeds_allocated": 0},
            {"period_label": "FY2", "projected_requirement": 5000000, "available_from_operations": 4000000, "ipo_proceeds_allocated": 0},
        ])
        self.assertEqual(out["rows"][1]["cumulative_gap"], 2000000.0)

    def test_sorted_by_period_label(self):
        out = ie.working_capital_adequacy([
            {"period_label": "FY2", "projected_requirement": 100, "available_from_operations": 100},
            {"period_label": "FY1", "projected_requirement": 100, "available_from_operations": 100},
        ])
        self.assertEqual(out["rows"][0]["period_label"], "FY1")


class PeerComparisonTests(unittest.TestCase):
    def test_pe_and_pbv_computed(self):
        out = ie.peer_comparison([{"peer_name": "A", "market_price": 500, "eps": 25, "book_value_per_share": 200}], {})
        self.assertEqual(out["peers"][0]["pe_ratio"], 20.0)
        self.assertEqual(out["peers"][0]["pbv_ratio"], 2.5)

    def test_implied_price_at_avg_pe(self):
        out = ie.peer_comparison(
            [{"peer_name": "A", "market_price": 500, "eps": 25}, {"peer_name": "B", "market_price": 600, "eps": 30}],
            {"eps": 20})
        self.assertEqual(out["avg_pe"], 20.0)
        self.assertEqual(out["implied_price_at_avg_pe"], 400.0)

    def test_zero_eps_peer_excluded_from_pe(self):
        out = ie.peer_comparison([{"peer_name": "A", "market_price": 500, "eps": 0}], {})
        self.assertIsNone(out["peers"][0]["pe_ratio"])

    def test_no_peers_no_crash(self):
        out = ie.peer_comparison([], {})
        self.assertIsNone(out["avg_pe"])
        self.assertEqual(out["peers"], [])


class PricingAnalysisTests(unittest.TestCase):
    def test_implied_pe_and_gap(self):
        out = ie.pricing_analysis({"face_value": 100, "proposed_price": 400, "subject_eps": 20, "valuation_per_share": 450})
        self.assertEqual(out["implied_pe"], 20.0)
        self.assertEqual(out["gap_vs_valuation"], -50.0)
        self.assertEqual(out["premium_to_face_value_pct"], 300.0)

    def test_missing_eps_omits_implied_pe(self):
        out = ie.pricing_analysis({"face_value": 100, "proposed_price": 400})
        self.assertNotIn("implied_pe", out)
        self.assertNotIn("subject_eps", out)


class ReadinessSummaryTests(unittest.TestCase):
    def test_area_completion(self):
        out = ie.readiness_summary([
            {"area": "Readiness", "status": "done"}, {"area": "Readiness", "status": "pending"},
        ])
        self.assertEqual(out["areas"]["Readiness"]["completion_pct"], 50.0)

    def test_eligibility_met_and_not_met(self):
        out = ie.readiness_summary([
            {"id": 1, "area": "Eligibility", "criterion": "Capital", "threshold_value": "50000000", "actual_value": "70000000"},
            {"id": 2, "area": "Eligibility", "criterion": "Track record", "threshold_value": "3", "actual_value": "2"},
        ])
        self.assertEqual(out["eligibility_not_met_count"], 1)
        self.assertTrue(out["eligibility"][0]["met"])
        self.assertFalse(out["eligibility"][1]["met"])

    def test_eligibility_unconfirmed_when_no_threshold(self):
        out = ie.readiness_summary([{"id": 1, "area": "Eligibility", "criterion": "X", "threshold_value": None, "actual_value": None}])
        self.assertEqual(out["eligibility_unconfirmed_count"], 1)
        self.assertIsNone(out["eligibility"][0]["met"])

    def test_non_numeric_threshold_unconfirmed_not_crash(self):
        out = ie.readiness_summary([{"id": 1, "area": "Eligibility", "criterion": "X", "threshold_value": "n/a", "actual_value": "yes"}])
        self.assertIsNone(out["eligibility"][0]["met"])


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