"""
公开只读状态接口（非管理员也可访问）

用途：
- 普通用户能看到：后端是否在线、启动时间、推荐是否在更新（snapshot 时间）
- recommendations-viewer 也可复用该接口展示“服务状态”

安全原则：
- 不返回任何敏感信息（不返回密钥、密码、完整 Redis URL 等）
"""

from __future__ import annotations

import json
import os
import time
from datetime import datetime, timedelta, timezone
from typing import Any, Dict, Optional, Tuple

from fastapi import APIRouter

try:
    import redis.asyncio as redis_async
except Exception:  # pragma: no cover
    redis_async = None


router = APIRouter(prefix="/api/public", tags=["public"])

_STARTED_AT_MS = int(time.time() * 1000)

REDIS_KEY_RECOMMENDATIONS_SNAPSHOT = "recommendations:snapshot"


def _beijing_time_str(ts_ms: Optional[int] = None) -> str:
    beijing_tz = timezone(timedelta(hours=8))
    if ts_ms is None:
        return datetime.now(tz=beijing_tz).strftime("%Y-%m-%d %H:%M:%S")
    return datetime.fromtimestamp(ts_ms / 1000, tz=beijing_tz).strftime("%Y-%m-%d %H:%M:%S")


def _mask_redis_url(redis_url: str) -> str:
    s = (redis_url or "").strip()
    if not s:
        return ""
    # 简单脱敏：去掉 username/password（如果有）
    # rediss://user:pass@host:6379/0 -> rediss://***@host:6379/0
    if "://" in s and "@" in s:
        scheme, rest = s.split("://", 1)
        creds_and_host = rest
        # 仅替换 @ 前面的内容
        idx = creds_and_host.rfind("@")
        if idx > 0:
            return f"{scheme}://***@{creds_and_host[idx+1:]}"
    return s


def _redis_connection_kwargs() -> Tuple[str, Dict[str, Any]]:
    redis_url = (os.getenv("REDIS_URL", "") or "").strip() or "redis://localhost:6379"
    username = os.getenv("REDIS_USERNAME", None)
    password = os.getenv("REDIS_PASSWORD", None)
    ssl_cert_reqs = (os.getenv("REDIS_SSL_CERT_REQS", "required") or "required").strip()
    ssl_ca_certs = os.getenv("REDIS_SSL_CA_CERTS", None)

    select = os.getenv("REDIS_SELECT", None)
    try:
        select_i = int(select) if select is not None else 0
    except Exception:
        select_i = 0

    kwargs: Dict[str, Any] = {"decode_responses": True}
    if username:
        kwargs["username"] = username
    if password:
        kwargs["password"] = password
    kwargs["db"] = select_i

    use_tls = redis_url.startswith("rediss://") or (os.getenv("REDIS_USE_TLS", "False").lower() == "true")
    if use_tls and not redis_url.startswith("rediss://"):
        if redis_url.startswith("redis://"):
            redis_url = redis_url.replace("redis://", "rediss://", 1)
        else:
            redis_url = f"rediss://{redis_url}"

    if use_tls or redis_url.startswith("rediss://"):
        kwargs["ssl_cert_reqs"] = ssl_cert_reqs
        if ssl_ca_certs:
            kwargs["ssl_ca_certs"] = ssl_ca_certs
        kwargs["ssl_check_hostname"] = (ssl_cert_reqs == "required")

    return redis_url, kwargs


async def _get_redis():
    if redis_async is None:
        return None
    redis_url, kwargs = _redis_connection_kwargs()
    try:
        client = redis_async.from_url(redis_url, **kwargs)
        await client.ping()
        return client
    except Exception:
        return None


async def _get_cached_json(client, key: str) -> Optional[Any]:
    try:
        raw = await client.get(key)
        if not raw:
            return None
        return json.loads(raw)
    except Exception:
        return None


@router.get("/status")
async def public_status():
    """
    公共状态：
    - backend：在线/启动时间
    - redis：可用性（不暴露密码）
    - recommendations：snapshot 最新生成时间（若推荐进程在跑，会持续更新）
    """
    now_ms = int(time.time() * 1000)

    # Redis + 推荐快照
    redis_ok = False
    reco: Dict[str, Any] = {"snapshot_ok": False}
    redis_meta: Dict[str, Any] = {"ok": False, "db": int(os.getenv("REDIS_SELECT", "0") or 0), "url": _mask_redis_url(os.getenv("REDIS_URL", ""))}

    rds = await _get_redis()
    if rds is not None:
        redis_ok = True
        redis_meta["ok"] = True
        try:
            snap = await _get_cached_json(rds, REDIS_KEY_RECOMMENDATIONS_SNAPSHOT)
        except Exception:
            snap = None

        if isinstance(snap, dict):
            gen_ms = snap.get("generated_at_ms")
            try:
                gen_ms = int(gen_ms) if gen_ms is not None else None
            except Exception:
                gen_ms = None
            count = snap.get("count")
            try:
                count = int(count) if count is not None else None
            except Exception:
                count = None
            age_sec = None
            if gen_ms:
                age_sec = max(0, int((now_ms - gen_ms) / 1000))
            reco = {
                "snapshot_ok": True,
                "generated_at_ms": gen_ms,
                "generated_at": snap.get("generated_at"),
                "generated_at_beijing": _beijing_time_str(gen_ms) if gen_ms else None,
                "age_sec": age_sec,
                "count": count,
                "ttl_sec": snap.get("ttl_sec"),
            }

        try:
            await rds.close()
        except Exception:
            pass

    return {
        "backend": {
            "running": True,
            "started_at_ms": _STARTED_AT_MS,
            "started_at": _beijing_time_str(_STARTED_AT_MS),
            "now_ms": now_ms,
            "now": _beijing_time_str(now_ms),
        },
        "redis": redis_meta,
        "recommendations": reco,
        "auth": {
            "enabled": (os.getenv("ATS_AUTH_ENABLED") or "true").strip().lower() not in {"0", "false", "no"},
        },
    }

