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

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

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


class SystematicSampleTests(unittest.TestCase):
    def test_basic_interval(self):
        out = ae.systematic_sample(1000, 25, 10)
        self.assertEqual(out["interval"], 40)
        self.assertEqual(out["selected_positions"][:3], [10, 50, 90])
        self.assertEqual(out["actual_count"], 25)

    def test_default_start_point(self):
        out = ae.systematic_sample(100, 10)
        self.assertEqual(out["start_point"], 1)
        self.assertEqual(out["selected_positions"][0], 1)

    def test_zero_population_no_crash(self):
        out = ae.systematic_sample(0, 10, 1)
        self.assertEqual(out["selected_positions"], [])
        self.assertEqual(out["interval"], 0)

    def test_zero_sample_size_no_crash(self):
        out = ae.systematic_sample(1000, 0, 1)
        self.assertEqual(out["selected_positions"], [])

    def test_sample_size_exceeds_population_stops_at_population_end(self):
        out = ae.systematic_sample(10, 25, 1)
        self.assertEqual(out["interval"], 1)
        self.assertTrue(all(p <= 10 for p in out["selected_positions"]))
        self.assertLessEqual(out["actual_count"], 10)

    def test_start_point_near_end_truncates(self):
        out = ae.systematic_sample(100, 10, 95)
        self.assertLess(out["actual_count"], 10)


class TestItemSummaryTests(unittest.TestCase):
    def test_groups_by_area_and_status(self):
        items = [
            {"area": "Bank", "status": "matched", "book_amount": 100000, "tested_amount": 100000},
            {"area": "Bank", "status": "exception", "book_amount": 50000, "tested_amount": 45000},
            {"area": "Debtors", "status": "open", "book_amount": 20000},
        ]
        out = ae.test_item_summary(items)
        self.assertEqual(out["areas"]["Bank"]["count"], 2)
        self.assertEqual(out["areas"]["Bank"]["exceptions"], 1)
        self.assertEqual(out["areas"]["Bank"]["variance_total"], -5000.0)
        self.assertEqual(out["total_items"], 3)
        self.assertEqual(out["total_exceptions"], 1)

    def test_confirmation_status_tallies(self):
        items = [
            {"area": "Debtors", "status": "open", "book_amount": 1000, "confirmation_status": "sent"},
            {"area": "Debtors", "status": "matched", "book_amount": 2000, "confirmation_status": "received_agreed"},
            {"area": "Debtors", "status": "exception", "book_amount": 3000, "confirmation_status": "received_discrepancy"},
        ]
        out = ae.test_item_summary(items)
        g = out["areas"]["Debtors"]
        self.assertEqual(g["confirmations_sent"], 3)
        self.assertEqual(g["confirmations_received"], 1)
        self.assertEqual(g["confirmations_discrepancy"], 1)

    def test_untested_amount_excluded_from_variance(self):
        out = ae.test_item_summary([{"area": "Inventory", "status": "open", "book_amount": 5000}])
        self.assertEqual(out["areas"]["Inventory"]["tested_total"], 0.0)
        self.assertEqual(out["areas"]["Inventory"]["variance_total"], 0.0)

    def test_empty_no_crash(self):
        out = ae.test_item_summary([])
        self.assertEqual(out["total_items"], 0)
        self.assertEqual(out["overall_exception_rate_pct"], 0.0)

    def test_exception_rate_computation(self):
        items = [{"area": "Revenue", "status": "exception", "book_amount": 1}] * 3 + \
                [{"area": "Revenue", "status": "matched", "book_amount": 1}]
        out = ae.test_item_summary(items)
        self.assertEqual(out["areas"]["Revenue"]["exception_rate_pct"], 75.0)


class AnalyticalReviewTests(unittest.TestCase):
    def test_variance_beyond_threshold_flags(self):
        out = ae.analytical_review([
            {"metric": "Gross margin %", "current_period_value": 30, "expected_value": 20, "threshold_pct": 10},
        ])
        self.assertTrue(out["rows"][0]["flagged"])
        self.assertEqual(out["flagged_count"], 1)

    def test_variance_within_threshold_not_flagged(self):
        out = ae.analytical_review([
            {"metric": "Gross margin %", "current_period_value": 21, "expected_value": 20, "threshold_pct": 10},
        ])
        self.assertFalse(out["rows"][0]["flagged"])
        self.assertEqual(out["flagged_count"], 0)

    def test_boundary_exactly_at_threshold_not_flagged(self):
        # variance_pct == threshold_pct exactly must NOT flag (strict > only)
        out = ae.analytical_review([
            {"metric": "M", "current_period_value": 22, "expected_value": 20, "threshold_pct": 10},
        ])
        self.assertEqual(out["rows"][0]["variance_pct"], 10.0)
        self.assertFalse(out["rows"][0]["flagged"])

    def test_no_expected_value_not_flagged(self):
        out = ae.analytical_review([{"metric": "M", "current_period_value": 100}])
        self.assertIsNone(out["rows"][0]["variance_pct"])
        self.assertFalse(out["rows"][0]["flagged"])

    def test_unexplained_flagged_count(self):
        out = ae.analytical_review([
            {"metric": "A", "current_period_value": 50, "expected_value": 20, "threshold_pct": 10, "explanation": "one-off sale"},
            {"metric": "B", "current_period_value": 50, "expected_value": 20, "threshold_pct": 10},
        ])
        self.assertEqual(out["flagged_count"], 2)
        self.assertEqual(out["unexplained_flagged_count"], 1)

    def test_expected_value_zero_no_division_error(self):
        out = ae.analytical_review([{"metric": "M", "current_period_value": 10, "expected_value": 0, "threshold_pct": 10}])
        self.assertIsNone(out["rows"][0]["variance_pct"])
        self.assertFalse(out["rows"][0]["flagged"])


class GoingConcernSummaryTests(unittest.TestCase):
    def test_groups_by_category(self):
        out = ae.going_concern_summary([
            {"category": "Financial", "present": True},
            {"category": "Financial", "present": False},
            {"category": "Operating", "present": True},
        ])
        self.assertEqual(out["by_category"]["Financial"], {"total": 2, "present": 1})
        self.assertEqual(out["present_count"], 2)
        self.assertEqual(out["total_count"], 3)

    def test_missing_category_defaults_other(self):
        out = ae.going_concern_summary([{"present": True}])
        self.assertIn("Other", out["by_category"])

    def test_empty_no_crash(self):
        out = ae.going_concern_summary([])
        self.assertEqual(out["total_count"], 0)
        self.assertEqual(out["present_count"], 0)


class ChecklistSummaryTests(unittest.TestCase):
    def test_completion_pct(self):
        out = ae.checklist_summary([
            {"area": "Completion", "status": "done"},
            {"area": "Completion", "status": "pending"},
            {"area": "Completion", "status": "done"},
        ])
        self.assertEqual(out["Completion"]["total"], 3)
        self.assertEqual(out["Completion"]["done"], 2)
        self.assertAlmostEqual(out["Completion"]["completion_pct"], 66.67, places=2)

    def test_na_status_not_counted_as_done(self):
        out = ae.checklist_summary([{"area": "NFRS Compliance", "status": "na"}])
        self.assertEqual(out["NFRS Compliance"]["done"], 0)

    def test_empty_no_crash(self):
        out = ae.checklist_summary([])
        self.assertEqual(out, {})


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