from __future__ import annotations

import json
import os
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from health_client import (
    AccountSnapshot,
    ExtraUsageSummary,
    HealthStatus,
    NamedLimit,
    SpendSummary,
)
from health_store import HealthSnapshotStore


def test_write_is_atomic_and_serializes_snapshots(tmp_path, monkeypatch):
    cache_path = tmp_path / "health_cache.json"
    cache_path.write_text('{"existing": true}', encoding="utf-8")
    store = HealthSnapshotStore(cache_path, stale_after_s=60)
    snapshots = {
        "rafa": AccountSnapshot(HealthStatus.OK, 13, 27),
        "roy": AccountSnapshot(HealthStatus.BROKEN, None, None),
    }
    captured = {}
    real_replace = Path.replace

    def fake_replace(self, target):
        captured["target_before_replace"] = Path(target).read_text(encoding="utf-8")
        captured["temp_payload"] = self.read_text(encoding="utf-8")
        return real_replace(self, target)

    monkeypatch.setattr(Path, "replace", fake_replace)

    store.write(snapshots)

    data = json.loads(cache_path.read_text(encoding="utf-8"))
    assert data == {
        "rafa": {
            "status": "ok",
            "primary_used_pct": 13,
            "secondary_used_pct": 27,
            "primary_reset_at": None,
            "secondary_reset_at": None,
            "checked_at": None,
            "detail": None,
            "named_limits": [],
            "extra_usage": None,
            "spend": None,
        },
        "roy": {
            "status": "broken",
            "primary_used_pct": None,
            "secondary_used_pct": None,
            "primary_reset_at": None,
            "secondary_reset_at": None,
            "checked_at": None,
            "detail": None,
            "named_limits": [],
            "extra_usage": None,
            "spend": None,
        },
    }
    assert captured["target_before_replace"] == '{"existing": true}'
    assert json.loads(captured["temp_payload"]) == data


def test_read_skips_bad_entries_and_keeps_valid_snapshots(tmp_path):
    cache_path = tmp_path / "health_cache.json"
    cache_path.write_text(
        json.dumps(
            {
                "rafa": {
                    "status": "ok",
                    "primary_used_pct": 13,
                    "secondary_used_pct": 27,
                },
                "bad-status": {
                    "status": "missing",
                    "primary_used_pct": 1,
                    "secondary_used_pct": 2,
                },
                "bad-pct": {
                    "status": "ok",
                    "primary_used_pct": "13",
                    "secondary_used_pct": None,
                },
            }
        ),
        encoding="utf-8",
    )

    snapshots = HealthSnapshotStore(cache_path, stale_after_s=60).read()

    assert snapshots == {
        "rafa": AccountSnapshot(HealthStatus.OK, 13, 27),
        "bad-pct": AccountSnapshot(HealthStatus.OK, None, None),
    }


def test_read_fresh_respects_staleness_boundary(tmp_path, monkeypatch):
    cache_path = tmp_path / "health_cache.json"
    cache_path.write_text(
        json.dumps(
            {
                "rafa": {
                    "status": "ok",
                    "primary_used_pct": 13,
                    "secondary_used_pct": 27,
                }
            }
        ),
        encoding="utf-8",
    )
    os.utime(cache_path, (1000.0, 1000.0))
    store = HealthSnapshotStore(cache_path, stale_after_s=60)
    monkeypatch.setattr("health_store.time.time", lambda: 1060.0)

    assert store.age_seconds() == 60.0
    assert store.read_fresh() == {
        "rafa": AccountSnapshot(HealthStatus.OK, 13, 27),
    }

    monkeypatch.setattr("health_store.time.time", lambda: 1060.1)

    assert store.age_seconds() == 60.09999999999991
    assert store.read_fresh() is None


def test_age_seconds_returns_none_for_missing_file(tmp_path):
    store = HealthSnapshotStore(tmp_path / "missing.json", stale_after_s=60)

    assert store.age_seconds() is None
    assert store.read_fresh() is None


def test_read_old_entries_and_round_trip_extended_entries(tmp_path):
    cache_path = tmp_path / "health_cache.json"
    cache_path.write_text(
        json.dumps(
            {
                "legacy": {
                    "status": "ok",
                    "primary_used_pct": 5,
                    "secondary_used_pct": 7,
                },
                "extended": {
                    "status": "ok",
                    "primary_used_pct": 13,
                    "secondary_used_pct": 27,
                    "primary_reset_at": 1_700_000_300.0,
                    "secondary_reset_at": 1_800_000_000.0,
                    "checked_at": 1_700_000_123.0,
                    "detail": "limits unavailable",
                    "named_limits": [
                        {
                            "kind": "five_hour",
                            "group": "primary",
                            "percent": 13,
                            "resets_at": 1_700_000_300.0,
                            "active": True,
                        },
                        {
                            "kind": "ignored",
                            "group": "other",
                            "percent": None,
                            "resets_at": None,
                            "active": "bad",
                        },
                    ],
                    "extra_usage": {
                        "used": 3.0,
                        "limit": 10.0,
                        "unit": "hours",
                        "display": "3 / 10 hours",
                    },
                    "spend": {
                        "amount": 12.5,
                        "limit": 50.0,
                        "currency": "USD",
                        "display": "$12.50 / $50",
                    },
                    "unknown": "ignored",
                },
            }
        ),
        encoding="utf-8",
    )

    store = HealthSnapshotStore(cache_path, stale_after_s=60)
    snapshots = store.read()

    assert snapshots == {
        "legacy": AccountSnapshot(HealthStatus.OK, 5, 7),
        "extended": AccountSnapshot(
            status=HealthStatus.OK,
            primary_used_pct=13,
            secondary_used_pct=27,
            primary_reset_at=1_700_000_300.0,
            secondary_reset_at=1_800_000_000.0,
            checked_at=1_700_000_123.0,
            detail="limits unavailable",
            named_limits=(
                NamedLimit("five_hour", "primary", 13, 1_700_000_300.0, True),
            ),
            extra_usage=ExtraUsageSummary(
                used=3.0,
                limit=10.0,
                unit="hours",
                display="3 / 10 hours",
            ),
            spend=SpendSummary(
                amount=12.5,
                limit=50.0,
                currency="USD",
                display="$12.50 / $50",
            ),
        ),
    }

    store.write(snapshots)

    assert store.read() == snapshots
