"""
Unit tests for server/ca_assistant.py's domain-based system-prompt loading
— the fix that keeps a single request under a free-tier provider's
tokens-per-minute budget by loading only the reasoning module(s) a
question actually touches, instead of always concatenating all of them.

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

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


class SystemPromptLoadingTests(unittest.TestCase):
    def test_no_domains_loads_only_base_prompt(self):
        base = ca._load_system_prompt([])
        full = ca._load_system_prompt(list(ca._DOMAIN_MODULE_FILES.keys()))
        self.assertLess(len(base), len(full))
        self.assertIn("Identity and Mission", base)

    def test_single_domain_adds_exactly_its_module(self):
        base_len = len(ca._load_system_prompt([]))
        with_vat = ca._load_system_prompt(["vat"])
        self.assertGreater(len(with_vat), base_len)
        with open(os.path.join(ca.PROMPT_DIR, "tax_advisory.md"), encoding="utf-8") as f:
            self.assertIn(f.read()[:200], with_vat)

    def test_multiple_domains_sharing_a_module_dont_duplicate_it(self):
        # income_tax, tds and vat all map to tax_advisory.md
        single = ca._load_system_prompt(["vat"])
        combined = ca._load_system_prompt(["income_tax", "tds", "vat"])
        self.assertEqual(len(single), len(combined))

    def test_every_domain_keyword_entry_maps_to_a_real_file(self):
        for domain in ca._DOMAIN_KEYWORDS:
            self.assertIn(domain, ca._DOMAIN_MODULE_FILES, f"{domain} has no prompt module mapping")
            fname = ca._DOMAIN_MODULE_FILES[domain]
            self.assertTrue(os.path.isfile(os.path.join(ca.PROMPT_DIR, fname)), f"{fname} missing on disk")

    def test_full_concatenation_stays_under_a_reasonable_ceiling(self):
        # Regression guard: if a new module is ever added without checking
        # size, this catches the free-tier budget problem before it ships.
        full = ca._load_system_prompt(list(ca._DOMAIN_MODULE_FILES.keys()))
        self.assertLess(len(full), 60000)   # ~15k tokens — the original all-modules size

    def test_single_domain_prompt_fits_comfortably_under_groq_free_tier_budget(self):
        # 8000 TPM is the tightest real budget observed on Groq's free tier
        # for the models this app defaults to; a single-domain question
        # (the common case) must leave headroom for context + reply.
        for domain in ca._DOMAIN_KEYWORDS:
            prompt = ca._load_system_prompt([domain])
            approx_tokens = len(prompt) // 4
            self.assertLess(approx_tokens, 8000, f"domain '{domain}' alone is too large for the free tier")

    def test_result_is_cached_per_domain_combination(self):
        a = ca._load_system_prompt(["audit"])
        b = ca._load_system_prompt(["audit"])
        self.assertIs(a, b)


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