"""图形验证码服务：简单算术题（Redis 优先，内存回退）"""

import secrets
import time

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel

from app.core.cache import cache

async def consume_verify_token(verify_token: str) -> bool:
    """消费一次性验证码令牌，供注册/登录等接口集成验证码"""
    stored = await _pop(VERIFY_PREFIX + verify_token)
    return stored is not None

router = APIRouter()

CAPTCHA_PREFIX = "captcha:"
VERIFY_PREFIX = "captcha_verify:"

# 内存回退（Redis 不可用时）
_mem_store: dict[str, dict] = {}


async def _store(key: str, value: dict, ttl: int):
    ok = await cache.set(key, value, ttl=ttl)
    if not ok:
        _mem_store[key] = {**value, "_expires": time.time() + ttl}


async def _pop(key: str) -> dict | None:
    val = await cache.pop(key)
    if val is not None:
        return val
    stored = _mem_store.pop(key, None)
    if stored and stored.get("_expires", 0) > time.time():
        return {k: v for k, v in stored.items() if k != "_expires"}
    return None


@router.get("/generate", summary="生成验证码")
async def generate_captcha():
    """生成算术验证码：返回 {id, question}，前端渲染为图片或文字"""
    op = secrets.choice(["+", "-", "x"])
    if op == "x":
        a = secrets.randbelow(9) + 1    # 1-9，保证结果不超过81
        b = secrets.randbelow(9) + 1
        answer = a * b
    else:
        a = secrets.randbelow(20) + 1    # 1-20
        b = secrets.randbelow(20) + 1
        if op == "-":
            a, b = max(a, b), min(a, b)
            answer = a - b
        else:
            answer = a + b

    captcha_id = secrets.token_hex(16)
    await _store(CAPTCHA_PREFIX + captcha_id, {"answer": answer}, ttl=300)

    return {"id": captcha_id, "question": f"{a} {op} {b} = ?", "expires_in": 300}


class CaptchaVerify(BaseModel):
    captcha_id: str
    captcha_answer: int


@router.post("/verify", summary="验证码校验")
async def verify_captcha(req: CaptchaVerify):
    """验证验证码答案，消耗一次性"""
    stored = await _pop(CAPTCHA_PREFIX + req.captcha_id)
    if not stored:
        raise HTTPException(status_code=400, detail="验证码已过期，请刷新")
    if stored["answer"] != req.captcha_answer:
        raise HTTPException(status_code=400, detail="验证码错误")
    # 验证通过，返回一次性令牌用于注册/登录
    verify_token = secrets.token_hex(16)
    await _store(VERIFY_PREFIX + verify_token, {"verified": True}, ttl=600)
    return {"status": "ok", "verify_token": verify_token}
