"""Проверка initData Telegram Mini App."""

from __future__ import annotations

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


def validate_init_data(init_data: str, bot_token: str, *, max_age: int = 86400) -> dict:
    raw = str(init_data or "").strip()
    if not raw:
        raise ValueError("Откройте мини-приложение из бота")
    parsed = dict(parse_qsl(raw, keep_blank_values=True))
    received_hash = parsed.pop("hash", "")
    if not received_hash:
        raise ValueError("Нет подписи Telegram")
    data_check = "\n".join(f"{key}={value}" for key, value in sorted(parsed.items()))
    secret = hmac.new(b"WebAppData", bot_token.encode("utf-8"), hashlib.sha256).digest()
    calculated = hmac.new(secret, data_check.encode("utf-8"), hashlib.sha256).hexdigest()
    if not hmac.compare_digest(calculated, received_hash):
        raise ValueError("Неверная подпись Telegram")
    try:
        auth_date = int(parsed.get("auth_date") or 0)
    except (TypeError, ValueError):
        auth_date = 0
    if auth_date <= 0 or abs(time.time() - auth_date) > max_age:
        raise ValueError("Сессия мини-приложения устарела, откройте его заново")
    try:
        user = json.loads(parsed.get("user") or "")
    except (TypeError, ValueError, json.JSONDecodeError) as exc:
        raise ValueError("Нет данных пользователя") from exc
    if not isinstance(user, dict) or not user.get("id"):
        raise ValueError("Нет данных пользователя")
    user["id"] = int(user["id"])
    return user


def make_media_token(user_id: int, bot_token: str, *, ttl: int = 7 * 86400) -> str:
    exp = int(time.time()) + int(ttl)
    payload = f"{int(user_id)}.{exp}"
    sig = hmac.new(bot_token.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256).hexdigest()[:20]
    return f"{payload}.{sig}"


def parse_media_token(token: str, bot_token: str) -> int:
    parts = str(token or "").split(".")
    if len(parts) != 3:
        raise ValueError("Недействительный доступ")
    user_id, exp, sig = parts
    payload = f"{user_id}.{exp}"
    expect = hmac.new(bot_token.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256).hexdigest()[:20]
    if not hmac.compare_digest(expect, sig):
        raise ValueError("Недействительный доступ")
    try:
        if int(exp) < time.time():
            raise ValueError("Сессия устарела")
        return int(user_id)
    except (TypeError, ValueError) as exc:
        raise ValueError("Недействительный доступ") from exc
