"""The public pool report carries measured allowances for active and limited accounts."""

import json
import os
import subprocess
import time
import unittest

import test_codex_reset as fixtures


class ResetReportingTest(fixtures.CodexPoolSandbox, unittest.TestCase):
    def report(self, used=60, enabled="1"):
        self.server.state["usage"] = {"rate_limit": {"allowed": True,
            "primary_window": {"used_percent": used, "limit_window_seconds": 604800,
                               "reset_at": int(time.time()) + 86400}},
            "rate_limit_reset_credits": {"available_count": 0}}
        base = f"http://127.0.0.1:{self.server.server_port}/wham"
        env = dict(os.environ, CODEX_ACCOUNTS_ROOT=str(self.pool), CODEX_MULTIACC_NO_SYNC="1",
                   CODEX_MULTIACC_AUTO_RESET=enabled, CODEX_MULTIACC_USAGE_URL=f"{base}/usage",
                   PYTHONDONTWRITEBYTECODE="1")
        for key in ("CODEX_MULTIACC_RESET_CREDITS_URL", "CODEX_MULTIACC_RESET_CONSUME_URL"):
            env.pop(key, None)
        result = subprocess.run([fixtures.REPO / "bin/codex-accounts", "limits", "--force", "--json"],
                                capture_output=True, text=True, env=env, timeout=20, check=False)
        self.assertEqual(result.returncode, 0, result.stderr)
        self.assertNotIn("private-credit", result.stdout)
        return json.loads(result.stdout)["accounts"][0]

    def test_active_account_reports_credits_without_redeeming(self):
        self.server.state["credits"] = {"available_count": 3, "credits": [
            {"id": "private-credit", "status": "available"}]}
        account = self.report()
        self.assertEqual(account["usage"]["reset_credits_available"], 3)
        self.assertTrue(account["usage"]["reset_credits_fetched_at"].endswith("Z"))
        self.assertEqual(self.server.state["credit_gets"], 1)
        self.assertEqual(self.server.state["posts"], [])

    def test_spent_account_reports_real_zero(self):
        self.server.state["credits"] = {"available_count": 0, "credits": []}
        account = self.report(100)
        self.assertTrue(account["limited"])
        self.assertEqual(account["usage"]["reset_credits_available"], 0)

    def test_redemption_reports_readback_instead_of_pre_reset_allowance(self):
        self.server.state["credits"] = {"available_count": 2, "credits": []}
        self.server.state["responses"] = [(200, {"code": "reset", "windows_reset": 1})]
        account = self.report(100)
        self.assertEqual(account["usage"]["reset_credits_available"], 1)
        self.assertTrue(account["usage"]["reset_credits_fetched_at"])
        self.assertEqual(self.server.state["credit_gets"], 2)
        self.assertEqual(len(self.server.state["posts"]), 1)

    def test_failed_or_invalid_reads_clear_previous_allowance_without_hiding_usage(self):
        self.server.state["credits"] = {"available_count": 2}
        self.report()
        for count in (None, "2", True, -1, 1.5, 1_000_001):
            with self.subTest(count=count):
                self.server.state["credits"] = {"available_count": count}
                usage = self.report()["usage"]
                self.assertNotIn("reset_credits_available", usage)
                self.assertNotIn("reset_credits_fetched_at", usage)
                self.assertEqual(usage["weekly_percent"], 60)
        self.assertEqual(self.server.state["posts"], [])

    def test_disabled_redemption_still_reports_allowance(self):
        self.server.state["credits"] = {"available_count": 2}
        self.assertEqual(self.report(100, enabled="0")["usage"]["reset_credits_available"], 2)
        self.assertEqual(self.server.state["posts"], [])

    def test_failed_readback_does_not_reuse_the_allowance_before_redemption(self):
        self.server.state["credits"] = {"available_count": 2, "credits": []}
        self.server.state["credits_after_post"] = []
        self.server.state["responses"] = [(200, {"code": "reset", "windows_reset": 1})]
        account = self.report(100)
        self.assertFalse(account["limited"])
        self.assertNotIn("reset_credits_available", account["usage"])
        self.assertEqual(len(self.server.state["posts"]), 1)


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