"""埋点健康度聚合:纯差分函数 + admin 端点。"""
from __future__ import annotations

from datetime import datetime, timezone

from app.admin.repositories.analytics_health import _cn_day, _rates, diff_snapshots


def _row(device, epoch, event, ts, **cum) -> dict:
    base = {"attempted": 0, "drop_capture": 0, "delivered": 0, "drop_undelivered": 0}
    base.update(cum)
    return {
        "device_id": device, "epoch_id": epoch, "event": event,
        "created_at": datetime(2026, 7, 1, ts, 0, tzinfo=timezone.utc),
        "app_ver": "0.2.12(62)", "oem": "ColorOS", "os": "Android 14",
        **base,
    }


def test_diff_first_row_is_full_cumulative() -> None:
    rows = [_row("d", "e", "video_play", 1, attempted=100, delivered=90)]
    out = diff_snapshots(rows)
    assert len(out) == 1
    assert out[0]["d_attempted"] == 100
    assert out[0]["d_delivered"] == 90


def test_diff_consecutive_delta() -> None:
    rows = [
        _row("d", "e", "video_play", 1, attempted=100, delivered=90),
        _row("d", "e", "video_play", 2, attempted=150, delivered=140),
    ]
    out = sorted(diff_snapshots(rows), key=lambda r: r["created_at"])
    assert out[1]["d_attempted"] == 50
    assert out[1]["d_delivered"] == 50


def test_diff_epoch_reset_new_partition() -> None:
    rows = [
        _row("d", "e1", "video_play", 1, attempted=100),
        _row("d", "e2", "video_play", 2, attempted=5),
    ]
    out = {(r["epoch_id"]): r["d_attempted"] for r in diff_snapshots(rows)}
    assert out["e1"] == 100
    assert out["e2"] == 5


def test_diff_clamps_negative_on_reorder() -> None:
    rows = [
        _row("d", "e", "video_play", 1, attempted=100),
        _row("d", "e", "video_play", 2, attempted=80),
    ]
    out = sorted(diff_snapshots(rows), key=lambda r: r["created_at"])
    assert out[1]["d_attempted"] == 0


def test_rates_computes_both_formulas() -> None:
    out = _rates({"attempted": 150, "drop_capture": 0, "delivered": 140, "drop_undelivered": 10})
    assert out["track_success_rate"] == 1.0
    assert out["report_success_rate"] == 140 / 150


def test_rates_zero_denominator_yields_none() -> None:
    out = _rates({"attempted": 0, "drop_capture": 0, "delivered": 0, "drop_undelivered": 0})
    assert out["track_success_rate"] is None
    assert out["report_success_rate"] is None


def test_cn_day_beijing_boundary() -> None:
    # UTC 15:59 → 北京 23:59 同日;UTC 16:00 → 北京 次日 00:00
    assert _cn_day(datetime(2026, 7, 1, 15, 59, tzinfo=timezone.utc)) == "2026-07-01"
    assert _cn_day(datetime(2026, 7, 1, 16, 0, tzinfo=timezone.utc)) == "2026-07-02"


def test_diff_same_timestamp_ordered_by_id() -> None:
    ts = datetime(2026, 7, 1, 1, 0, tzinfo=timezone.utc)
    # 相同 created_at,乱序传入(id=2 在前);应按 id 排序 → id=1(cum100) 在前
    rows = [
        {"id": 2, "device_id": "d", "epoch_id": "e", "event": "vp", "created_at": ts,
         "app_ver": "v", "oem": "o", "os": "s",
         "attempted": 150, "drop_capture": 0, "delivered": 0, "drop_undelivered": 0},
        {"id": 1, "device_id": "d", "epoch_id": "e", "event": "vp", "created_at": ts,
         "app_ver": "v", "oem": "o", "os": "s",
         "attempted": 100, "drop_capture": 0, "delivered": 0, "drop_undelivered": 0},
    ]
    out = diff_snapshots(rows)
    assert out[0]["d_attempted"] == 100  # id=1 sorts first → its cumulative
    assert out[1]["d_attempted"] == 50   # id=2 second → 150-100


import pytest
from fastapi.testclient import TestClient

from app.admin.main import admin_app
from app.admin.repositories import admin_user as admin_repo
from app.db.session import SessionLocal


@pytest.fixture()
def admin_client() -> TestClient:
    return TestClient(admin_app)


@pytest.fixture()
def admin_token() -> str:
    db = SessionLocal()
    try:
        if admin_repo.get_by_username(db, "health_admin") is None:
            admin_repo.create_admin(db, username="health_admin", password="pw", role="super_admin")
    finally:
        db.close()
    c = TestClient(admin_app)
    r = c.post("/admin/api/auth/login", json={"username": "health_admin", "password": "pw"})
    return r.json()["access_token"]


def _auth(t: str) -> dict:
    return {"Authorization": f"Bearer {t}"}


def _seed_two_snapshots(client: TestClient) -> None:
    for attempted, delivered in ((100, 90), (150, 140)):
        client.post("/api/v1/analytics/selfstat", json={
            "device_id": "d-health", "epoch_id": "e-health",
            "app_ver": "0.2.12(62)", "oem": "ColorOS", "os": "Android 14",
            "events": [{"event": "video_play", "attempted": attempted,
                        "drop_capture": 0, "delivered": delivered, "drop_undelivered": 0}],
        })


def test_health_overview_requires_auth(admin_client: TestClient) -> None:
    r = admin_client.get("/admin/api/analytics-health/overview",
                         params={"date_from": "2026-07-01T00:00:00Z", "date_to": "2030-01-01T00:00:00Z"})
    assert r.status_code == 401


def test_health_overview(client: TestClient, admin_client: TestClient, admin_token: str) -> None:
    _seed_two_snapshots(client)  # 播种走公开 app(ingest 端点在 app,不在 admin_app)
    r = admin_client.get(
        "/admin/api/analytics-health/overview",
        params={"date_from": "2026-07-01T00:00:00Z", "date_to": "2030-01-01T00:00:00Z"},
        headers=_auth(admin_token),
    )
    assert r.status_code == 200, r.text
    data = r.json()
    # 两快照累计 100→150,差分后 attempted 总 150(首快照 100 + 增量 50)
    assert data["attempted"] == 150
    assert data["track_success_rate"] == 1.0


def test_health_breakdown(client: TestClient, admin_client: TestClient, admin_token: str) -> None:
    _seed_two_snapshots(client)  # 播种走公开 app
    r = admin_client.get(
        "/admin/api/analytics-health/breakdown",
        params={"date_from": "2026-07-01T00:00:00Z", "date_to": "2030-01-01T00:00:00Z", "dim": "event"},
        headers=_auth(admin_token),
    )
    assert r.status_code == 200, r.text
    rows = r.json()
    assert any(row["key"] == "video_play" for row in rows)
