from typing import Annotated, Any

from fastapi import APIRouter, Depends, Header, Request, Response, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from pydantic import BaseModel, Field

from zbt.api.responses import success_response
from zbt.core.config import Settings
from zbt.core.errors import AppError
from zbt.domains.enrollment.service import EnrollmentService
from zbt.domains.identity.models import H5User
from zbt.domains.identity.service import H5AuthService

enrollment_bearer_scheme = HTTPBearer(auto_error=False)


class InsuredInput(BaseModel):
    age: int = Field(ge=0, le=120)
    region_code: str = Field(min_length=6, max_length=12)
    occupation_code: str = Field(min_length=1, max_length=32)


class CreateQuoteRequest(BaseModel):
    product_id: str = Field(min_length=26, max_length=26)
    plan_id: str = Field(min_length=26, max_length=26)
    insured: InsuredInput
    relationship: str = Field(pattern="^(SELF|PARENT|SPOUSE|CHILD)$")


class PersonInput(BaseModel):
    name: str = Field(min_length=1, max_length=64)
    id_no: str = Field(min_length=6, max_length=32)


class ContactInput(BaseModel):
    mobile: str = Field(min_length=11, max_length=11)


class CreateDraftRequest(BaseModel):
    quote_id: str = Field(min_length=26, max_length=26)
    applicant: PersonInput
    insured: PersonInput
    contact: ContactInput


class CreateOrderRequest(BaseModel):
    draft_id: str = Field(min_length=26, max_length=26)
    confirmation_token: str = Field(min_length=32, max_length=128)


class MockPaymentCallbackRequest(BaseModel):
    callback_no: str = Field(min_length=1, max_length=64)
    provider_transaction_no: str = Field(min_length=1, max_length=64)
    payment_no: str = Field(min_length=1, max_length=40)
    status: str = Field(pattern="^(SUCCEEDED|FAILED)$")
    amount_cents: int = Field(gt=0)
    occurred_at: str = Field(min_length=10, max_length=64)


def create_enrollment_router(
    service: EnrollmentService,
    h5_auth_service: H5AuthService,
    settings: Settings,
) -> APIRouter:
    router = APIRouter(tags=["enrollment"])

    def current_h5_user(
        credentials: Annotated[
            HTTPAuthorizationCredentials | None,
            Depends(enrollment_bearer_scheme),
        ],
    ) -> H5User:
        if credentials is None:
            raise AppError("AUTH_REQUIRED", "请先登录", 401)
        return h5_auth_service.authenticate_access(credentials.credentials)

    @router.post("/h5/quotes", status_code=status.HTTP_201_CREATED)
    def create_quote(
        payload: CreateQuoteRequest,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            service.create_quote(
                user,
                product_id=payload.product_id,
                plan_id=payload.plan_id,
                age=payload.insured.age,
                region_code=payload.insured.region_code,
                occupation_code=payload.insured.occupation_code,
                relationship=payload.relationship,
            ),
        )

    @router.post("/h5/enrollment-drafts", status_code=status.HTTP_201_CREATED)
    def create_draft(
        payload: CreateDraftRequest,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            service.create_draft(
                user,
                quote_id=payload.quote_id,
                applicant=payload.applicant.model_dump(),
                insured=payload.insured.model_dump(),
                contact=payload.contact.model_dump(),
            ),
        )

    @router.post(
        "/h5/enrollment-drafts/{draft_id}/confirmation",
        status_code=status.HTTP_201_CREATED,
    )
    def confirm_draft(
        draft_id: str,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(request, service.confirm_draft(user, draft_id))

    @router.post("/h5/orders", status_code=status.HTTP_201_CREATED)
    def create_order(
        payload: CreateOrderRequest,
        request: Request,
        response: Response,
        user: Annotated[H5User, Depends(current_h5_user)],
        idempotency_key: Annotated[
            str,
            Header(alias="Idempotency-Key", min_length=1, max_length=64),
        ],
    ) -> dict[str, Any]:
        data, created = service.create_order(
            user,
            draft_id=payload.draft_id,
            confirmation_token=payload.confirmation_token,
            idempotency_key=idempotency_key,
        )
        response.status_code = status.HTTP_201_CREATED if created else status.HTTP_200_OK
        return success_response(request, data)

    @router.post(
        "/h5/orders/{order_id}/payments",
        status_code=status.HTTP_201_CREATED,
    )
    def create_payment(
        order_id: str,
        request: Request,
        response: Response,
        user: Annotated[H5User, Depends(current_h5_user)],
        idempotency_key: Annotated[
            str,
            Header(alias="Idempotency-Key", min_length=1, max_length=64),
        ],
    ) -> dict[str, Any]:
        data, created = service.create_payment(
            user,
            order_id=order_id,
            idempotency_key=idempotency_key,
        )
        response.status_code = status.HTTP_201_CREATED if created else status.HTTP_200_OK
        return success_response(request, data)

    @router.post("/dev/mock-payments/{payment_id}/complete")
    def complete_mock_payment(
        payment_id: str,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        if not settings.dev_tools_enabled or settings.app_env == "production":
            raise AppError("DEV_TOOL_DISABLED", "本地模拟支付未启用", 404)
        return success_response(
            request,
            service.complete_mock_payment(user, payment_id=payment_id),
        )

    @router.post("/callbacks/mock-payment")
    def mock_payment_callback(
        payload: MockPaymentCallbackRequest,
        request: Request,
        signature: Annotated[
            str,
            Header(alias="X-Mock-Pay-Signature", min_length=1, max_length=128),
        ],
    ) -> dict[str, Any]:
        return success_response(
            request,
            service.handle_mock_callback(payload.model_dump(), signature),
        )

    @router.get("/h5/policies")
    def list_policies(
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(request, service.list_policies(user))

    @router.get("/h5/orders")
    def list_orders(
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(request, service.list_orders(user.id))

    return router
