"""Проверка Telegram Mini App initData и роли пользователя."""

from __future__ import annotations

import hashlib
import hmac
import json
import time
from urllib.parse import parse_qsl

from fastapi import HTTPException, Request

from api.db_api import count_admins, get_app_user, is_panel_worker, upsert_app_user
from server.config import ADMIN_TG_IDS, BOT_TOKEN, PANEL_BOT_TOKEN

MAX_AUTH_AGE = 86400 * 2


def _bot_tokens() -> list[str]:
    seen: set[str] = set()
    tokens: list[str] = []
    for token in (PANEL_BOT_TOKEN, BOT_TOKEN):
        value = str(token or "").strip()
        if value and value not in seen:
            seen.add(value)
            tokens.append(value)
    return tokens


def validate_webapp_init_data(init_data: str, bot_token: str | None = None) -> dict:
    if not init_data or not str(init_data).strip():
        raise ValueError("Нет initData")
    parsed = dict(parse_qsl(init_data, keep_blank_values=True))
    received_hash = parsed.pop("hash", None)
    if not received_hash:
        raise ValueError("Нет подписи Telegram")
    data_check_string = "\n".join(f"{k}={v}" for k, v in sorted(parsed.items()))
    tokens = [bot_token] if bot_token else _bot_tokens()
    matched = False
    for token in tokens:
        token = str(token or "").strip()
        if not token:
            continue
        secret_key = hmac.new(b"WebAppData", token.encode("utf-8"), hashlib.sha256).digest()
        calculated = hmac.new(secret_key, data_check_string.encode("utf-8"), hashlib.sha256).hexdigest()
        if hmac.compare_digest(calculated, received_hash):
            matched = True
            break
    if not matched:
        raise ValueError("Подпись Telegram недействительна")

    auth_date = parsed.get("auth_date")
    if auth_date:
        try:
            issued = int(auth_date)
        except (TypeError, ValueError):
            issued = 0
        if issued and abs(time.time() - issued) > MAX_AUTH_AGE:
            raise ValueError("Сессия Telegram устарела — откройте панель заново")

    user_raw = parsed.get("user") or ""
    try:
        user = json.loads(user_raw) if user_raw else {}
    except json.JSONDecodeError as exc:
        raise ValueError("Не удалось прочитать пользователя Telegram") from exc
    if not isinstance(user, dict) or not user.get("id"):
        raise ValueError("В initData нет пользователя")
    return user


def resolve_user(user: dict) -> dict:
    tg_id = int(user["id"])
    username = user.get("username")
    first_name = user.get("first_name")
    is_admin = tg_id in set(ADMIN_TG_IDS or ())
    existing = get_app_user(tg_id)
    if existing and existing.get("is_admin"):
        is_admin = True
    if not is_admin and not ADMIN_TG_IDS and count_admins() == 0:
        is_admin = True
    row = upsert_app_user(tg_id, username=username, first_name=first_name, is_admin=is_admin)
    admin = bool(row and row.get("is_admin"))
    worker = (not admin) and is_panel_worker(tg_id)
    return {
        "id": tg_id,
        "is_admin": admin,
        "is_worker": worker,
        "username": (row or {}).get("username") or username or "",
        "first_name": (row or {}).get("first_name") or first_name or "",
    }


def current_user_from_request(request: Request) -> dict:
    init_data = (
        request.headers.get("X-Telegram-Init-Data")
        or request.headers.get("X-Telegram-Init-Data".lower())
        or request.query_params.get("initData")
        or ""
    )
    try:
        tg_user = validate_webapp_init_data(init_data)
    except ValueError as exc:
        raise HTTPException(status_code=401, detail=str(exc) or "Откройте панель из Telegram") from exc
    return resolve_user(tg_user)
