"""后台服务订单与退订处理中心。"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import or_, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.config import settings
from app.core.deps import require_role
from app.database import get_db
from app.models.instance import Instance
from app.models.order import Order
from app.models.order_refund import OrderRefund
from app.models.upstream_action_log import UpstreamActionLog
from app.models.user import User
from app.routers import orders as order_helpers
from app.schemas.common import ApiResponse
from app.services import system_setting_service, upstream_action_service

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


def _action_summary(actions: list[UpstreamActionLog], refund: OrderRefund | None) -> dict:
    summary = upstream_action_service.summarize_resource_actions(actions)
    if refund and refund.resource_status:
        summary["status"] = refund.resource_status
        summary["label"] = upstream_action_service.RESOURCE_STATUS_LABELS.get(
            refund.resource_status,
            refund.resource_status,
        )
    return summary


async def _full_refund_count_cached(
    db: AsyncSession,
    cache: dict[int, int],
    user_id: int,
    reset_at=None,
) -> int:
    if user_id not in cache:
        cache[user_id] = await order_helpers._full_refund_count(db, user_id, reset_at)
    return cache[user_id]


async def _active_agent_cached(db: AsyncSession, cache: dict[int, bool], user_id: int) -> bool:
    if user_id not in cache:
        cache[user_id] = await order_helpers._is_active_agent(db, user_id)
    return cache[user_id]


async def _service_order_to_admin_dict(
    db: AsyncSession,
    order: Order,
    *,
    settings,
    full_refund_cache: dict[int, int],
    active_agent_cache: dict[int, bool],
    user: User | None,
) -> dict:
    instances = await order_helpers._load_order_instances(db, order)
    rewards = await order_helpers._load_order_point_rewards(db, order.id)
    refund = await order_helpers._latest_refund(db, order.id)
    actions = await order_helpers._load_order_actions(db, order.id)
    full_count = await _full_refund_count_cached(
        db,
        full_refund_cache,
        order.user_id,
        getattr(user, "full_refund_quota_reset_at", None) if user else None,
    )
    full_refund_unlimited = await _active_agent_cached(db, active_agent_cache, order.user_id)
    full_refund_limit = (
        order_helpers._full_refund_limit_for_user(settings, user)
        if user
        else int(settings.full_refund_limit)
    )
    policy = order_helpers._build_refund_policy(
        order,
        instances,
        rewards,
        full_count,
        refund,
        settings.full_refund_days,
        full_refund_limit,
        allow_full_refund=order_helpers._is_server_purchase_order(order),
        enforce_full_limit=order_helpers._is_server_purchase_order(order),
        full_refund_unlimited=full_refund_unlimited,
    )
    row = order_helpers._order_to_service_dict(order, instances, rewards, refund, policy, actions)
    row["user"] = {
        "id": user.id if user else order.user_id,
        "username": user.username if user else None,
        "email": user.email if user else None,
        "phone": user.phone if user else None,
        "nickname": user.nickname if user else None,
    }
    row["resource_summary"] = _action_summary(actions, refund)
    return row


@router.get("", response_model=ApiResponse)
async def list_admin_service_orders(
    keyword: str | None = Query(None),
    status: str | None = Query(None),
    refund_status: str | None = Query(None),
    refund_type: str | None = Query(None),
    resource_status: str | None = Query(None),
    user_id: int | None = Query(None),
    instance_id: int | None = Query(None),
    limit: int = Query(100, ge=1, le=300),
    offset: int = Query(0, ge=0),
    db: AsyncSession = Depends(get_db),
    _: User = Depends(_admin),
):
    stmt = select(Order).order_by(Order.id.desc()).limit(limit).offset(offset)
    if status:
        stmt = stmt.where(Order.status == status)
    if user_id:
        stmt = stmt.where(Order.user_id == user_id)
    if instance_id:
        stmt = stmt.where(
            Order.id.in_(select(Instance.order_id).where(Instance.id == instance_id))
        )
    if refund_status:
        stmt = stmt.where(
            Order.id.in_(select(OrderRefund.order_id).where(OrderRefund.status == refund_status))
        )
    if refund_type:
        stmt = stmt.where(
            Order.id.in_(select(OrderRefund.order_id).where(OrderRefund.refund_type == refund_type))
        )
    if resource_status:
        if resource_status == "none":
            stmt = stmt.where(
                ~Order.id.in_(
                    select(UpstreamActionLog.order_id).where(UpstreamActionLog.order_id.is_not(None))
                )
            )
        elif resource_status in ("running", "failed", "finished", "manual_handled", "ignored"):
            stmt = stmt.where(
                Order.id.in_(
                    select(OrderRefund.order_id).where(OrderRefund.resource_status == resource_status)
                )
            )

    if keyword:
        like = f"%{keyword}%"
        user_ids = select(User.id).where(
            or_(User.username.like(like), User.email.like(like), User.phone.like(like), User.nickname.like(like))
        )
        instance_order_ids = select(Instance.order_id).where(
            or_(Instance.hostname.like(like), Instance.main_ip.like(like))
        )
        stmt = stmt.where(
            or_(
                Order.out_order_no.like(like),
                Order.remark.like(like),
                Order.user_id.in_(user_ids),
                Order.id.in_(instance_order_ids),
            )
        )

    result = await db.execute(stmt)
    orders = list(result.scalars().all())

    user_ids = {int(order.user_id) for order in orders}
    users: dict[int, User] = {}
    if user_ids:
        user_result = await db.execute(select(User).where(User.id.in_(user_ids)))
        users = {int(user.id): user for user in user_result.scalars().all()}

    settings = await system_setting_service.get_business_settings(db)
    full_refund_cache: dict[int, int] = {}
    active_agent_cache: dict[int, bool] = {}
    data = [
        await _service_order_to_admin_dict(
            db,
            order,
            settings=settings,
            full_refund_cache=full_refund_cache,
            active_agent_cache=active_agent_cache,
            user=users.get(int(order.user_id)),
        )
        for order in orders
    ]
    return ApiResponse(data=data)


@router.get("/{order_id}", response_model=ApiResponse)
async def get_admin_service_order(
    order_id: int,
    db: AsyncSession = Depends(get_db),
    _: User = Depends(_admin),
):
    result = await db.execute(select(Order).where(Order.id == order_id))
    order = result.scalar_one_or_none()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")
    user_result = await db.execute(select(User).where(User.id == order.user_id))
    user = user_result.scalar_one_or_none()
    settings = await system_setting_service.get_business_settings(db)
    return ApiResponse(data=await _service_order_to_admin_dict(
        db,
        order,
        settings=settings,
        full_refund_cache={},
        active_agent_cache={},
        user=user,
    ))


@router.post("/{order_id}/unsubscribe", response_model=ApiResponse)
async def admin_unsubscribe_service_order(
    order_id: int,
    db: AsyncSession = Depends(get_db),
    _current: User = Depends(_admin),
):
    order = await db.scalar(select(Order).where(Order.id == order_id))
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")
    user = await db.get(User, order.user_id)
    if not user:
        raise HTTPException(status_code=404, detail="订单用户不存在")
    return await order_helpers.unsubscribe_order(order_id, current_user=user, db=db)
