from fastapi import APIRouter, Depends, Form, Query, Request
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.deps import get_current_user, require_role
from app.database import get_db
from app.models.user import User
from app.schemas.common import ApiResponse
from app.services import verification_service

router = APIRouter()
_admin = require_role("admin", "super_admin")


class VerificationIdentityRequest(BaseModel):
    real_name: str = Field(..., min_length=2, max_length=50)
    id_card_no: str = Field(..., min_length=15, max_length=18, pattern=r"^[\dXx]{15,18}$")


class VerificationThreeFactorRequest(VerificationIdentityRequest):
    phone: str = Field(..., min_length=5, max_length=20)


class VerificationRedirectRequest(VerificationIdentityRequest):
    return_url: str | None = Field(None, min_length=8, max_length=500)
    notify_url: str | None = Field(None, max_length=500)


class VerificationRedirectResultRequest(BaseModel):
    external_id: str | None = Field(None, max_length=128)
    record_id: int | None = None


class VerificationQuotaPurchaseRequest(BaseModel):
    count: int = Field(..., ge=1, le=100)


class AdminManualVerifyRequest(BaseModel):
    verified: bool
    reason: str | None = Field(None, max_length=500)


@router.get("/me/verification-status", response_model=ApiResponse)
async def get_verification_status(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.get_user_verification_status(db, current_user)
    return ApiResponse(data=data)


@router.get("/me/verification-options", response_model=ApiResponse)
async def get_verification_options(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    _ = current_user
    data = await verification_service.get_verification_options(db)
    return ApiResponse(data=data)


@router.post("/me/verification/two-factor", response_model=ApiResponse)
async def submit_two_factor_verification(
    body: VerificationIdentityRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.submit_two_factor(
        db,
        current_user,
        real_name=body.real_name,
        id_card_no=body.id_card_no,
    )
    return ApiResponse(data=data)


@router.post("/me/verification/three-factor", response_model=ApiResponse)
async def submit_three_factor_verification(
    body: VerificationThreeFactorRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.submit_three_factor(
        db,
        current_user,
        real_name=body.real_name,
        id_card_no=body.id_card_no,
        phone=body.phone,
    )
    return ApiResponse(data=data)


@router.post("/me/verification/face-api", response_model=ApiResponse)
async def submit_face_api_verification(
    real_name: str = Form(..., min_length=2, max_length=50),
    id_card_no: str = Form(..., min_length=15, max_length=18, pattern=r"^[\dXx]{15,18}$"),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.submit_two_factor(
        db,
        current_user,
        real_name=real_name,
        id_card_no=id_card_no,
    )
    return ApiResponse(data=data)


@router.post("/me/verification/redirect-session", response_model=ApiResponse)
async def create_redirect_verification_session(
    body: VerificationRedirectRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.create_redirect_session(
        db,
        current_user,
        real_name=body.real_name,
        id_card_no=body.id_card_no,
        return_url=body.return_url,
        notify_url=body.notify_url,
    )
    return ApiResponse(data=data)


@router.post("/me/verification/redirect-result", response_model=ApiResponse)
async def query_redirect_verification_result(
    body: VerificationRedirectResultRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.query_redirect_result(
        db,
        current_user,
        external_id=body.external_id,
        record_id=body.record_id,
    )
    return ApiResponse(data=data)


@router.post("/me/verification/quota/purchase", response_model=ApiResponse)
async def purchase_verification_quota(
    body: VerificationQuotaPurchaseRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.purchase_verification_quota(db, current_user, count=body.count)
    return ApiResponse(data=data, message="实名认证次数购买成功")


@router.api_route("/verification/notify/{provider_name}", methods=["GET", "POST"], response_model=ApiResponse)
async def verification_notify(
    provider_name: str,
    request: Request,
    db: AsyncSession = Depends(get_db),
):
    payload: dict[str, object] = dict(request.query_params)
    if request.method == "POST":
        content_type = request.headers.get("content-type", "")
        if "application/json" in content_type:
            body = await request.json()
            if isinstance(body, dict):
                payload.update(body)
        else:
            form = await request.form()
            payload.update(dict(form))
    data = await verification_service.handle_redirect_notify(db, provider_name=provider_name, payload=payload)
    return ApiResponse(data=data)


@router.get("/admin/verification-records", response_model=ApiResponse)
async def list_verification_records(
    status: str | None = Query(None),
    user_id: int | None = Query(None),
    page: int = Query(1, ge=1),
    per_page: int = Query(20, ge=1, le=100),
    _: User = Depends(_admin),
    db: AsyncSession = Depends(get_db),
):
    data = await verification_service.list_verification_records(
        db,
        status=status,
        user_id=user_id,
        page=page,
        per_page=per_page,
    )
    return ApiResponse(data=data)


@router.post("/admin/users/{user_id}/verification", response_model=ApiResponse)
async def manual_verify_user(
    user_id: int,
    body: AdminManualVerifyRequest,
    _: User = Depends(_admin),
    db: AsyncSession = Depends(get_db),
):
    result = await verification_service.manual_verify_user(
        db,
        user_id,
        verified=body.verified,
        reason=body.reason,
    )
    return ApiResponse(data=result)
