from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session

from app.core.database import get_db
from app.core.dependencies import get_current_admin
from app.core.responses import api_success
from app.models.admin import Admin
from app.models.entitlement import EntitlementPlan
from app.models.user import User
from app.schemas.admin import (
    EntitlementPlanSaveRequest,
    UserEntitlementAssignRequest,
    UserEntitlementBatchRenewRequest,
    UserEntitlementRenewRequest,
)
from app.services.admin_service import OperationLogService
from app.services.entitlement_service import EntitlementService, entitlement_dict, plan_dict
from app.services.topic_session_service import TopicSessionService

router = APIRouter()


@router.get("/entitlement/plan/list")
def list_entitlement_plans(
    includeDisabled: bool = Query(default=True),
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    plans = EntitlementService.list_plans(db, include_disabled=includeDisabled)
    return api_success([plan_dict(plan) for plan in plans])


@router.post("/entitlement/plan")
def create_entitlement_plan(
    payload: EntitlementPlanSaveRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    plan = EntitlementPlan()
    _apply_plan_payload(plan, payload)
    db.add(plan)
    db.flush()
    OperationLogService.write(db, admin_id=current_admin.id, module="entitlement", action="create_plan", target_id=plan.id)
    db.commit()
    db.refresh(plan)
    return api_success(plan_dict(plan))


@router.put("/entitlement/plan/{plan_id}")
def update_entitlement_plan(
    plan_id: int,
    payload: EntitlementPlanSaveRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    plan = db.get(EntitlementPlan, plan_id)
    if plan is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="权益版本不存在")
    _apply_plan_payload(plan, payload)
    db.add(plan)
    OperationLogService.write(db, admin_id=current_admin.id, module="entitlement", action="update_plan", target_id=plan.id)
    db.commit()
    db.refresh(plan)
    return api_success(plan_dict(plan))


@router.post("/user/{user_id}/entitlement")
def assign_user_entitlement(
    user_id: int,
    payload: UserEntitlementAssignRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    user = db.get(User, user_id)
    if user is None or user.is_deleted:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在")
    entitlement = EntitlementService.assign_user_plan(
        db,
        user=user,
        plan_id=payload.planId,
        operated_by=current_admin.id,
        effective_at=payload.effectiveAt,
        expired_at=payload.expiredAt,
        remark=payload.remark,
    )
    OperationLogService.write(
        db,
        admin_id=current_admin.id,
        module="entitlement",
        action="assign_user_plan",
        target_id=user.id,
    )
    db.commit()
    db.refresh(entitlement)
    view = EntitlementService.active_entitlement(
        db,
        user,
        monthly_topic_used=TopicSessionService.monthly_used_count(db, user.id),
    )
    return api_success(entitlement_dict(view))


@router.post("/user/{user_id}/entitlement/renew")
def renew_user_entitlement(
    user_id: int,
    payload: UserEntitlementRenewRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    user = db.get(User, user_id)
    if user is None or user.is_deleted:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在")
    EntitlementService.renew_user_plan(
        db,
        user=user,
        extension_days=payload.extensionDays,
        request_key=f"{payload.idempotencyKey}:{user.id}",
        operated_by=current_admin.id,
        remark=payload.remark,
    )
    OperationLogService.write(
        db,
        admin_id=current_admin.id,
        module="entitlement",
        action="renew_user_plan",
        target_id=user.id,
    )
    db.commit()
    view = EntitlementService.active_entitlement(
        db,
        user,
        monthly_topic_used=TopicSessionService.monthly_used_count(db, user.id),
    )
    return api_success(entitlement_dict(view))


@router.post("/user/entitlement/batch-renew")
def batch_renew_user_entitlement(
    payload: UserEntitlementBatchRenewRequest,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    succeeded: list[dict] = []
    failed: list[dict] = []
    for user_id in dict.fromkeys(payload.userIds):
        user = db.get(User, user_id)
        if user is None or user.is_deleted:
            failed.append({"userId": user_id, "reason": "用户不存在"})
            continue
        try:
            EntitlementService.renew_user_plan(
                db,
                user=user,
                extension_days=payload.extensionDays,
                request_key=f"{payload.idempotencyKey}:{user.id}",
                operated_by=current_admin.id,
                remark=payload.remark,
            )
            succeeded.append({"userId": user.id, "name": user.name})
        except HTTPException as exc:
            failed.append({"userId": user.id, "name": user.name, "reason": str(exc.detail)})
    OperationLogService.write(
        db,
        admin_id=current_admin.id,
        module="entitlement",
        action="batch_renew_user_plan",
        target_id=None,
        result="SUCCESS" if not failed else "PARTIAL",
    )
    db.commit()
    return api_success(
        {"succeeded": succeeded, "failed": failed, "successCount": len(succeeded), "failureCount": len(failed)}
    )


def _apply_plan_payload(plan: EntitlementPlan, payload: EntitlementPlanSaveRequest) -> None:
    plan.name = payload.name.strip()
    plan.plan_type = payload.planType
    plan.description = payload.description.strip() if payload.description else None
    plan.validity_days = payload.validityDays
    plan.monthly_topic_limit = payload.monthlyTopicLimit
    plan.enable_growth_profile = payload.enableGrowthProfile
    plan.enable_periodic_reports = payload.enablePeriodicReports
    plan.allow_help_card = payload.allowHelpCard
    plan.allow_share_draft = payload.allowShareDraft
    plan.deduct_quota = payload.deductQuota
    plan.status = payload.status
    plan.sort_order = payload.sortOrder
