"""商业不可变账期和管理审计历史。"""

from __future__ import annotations

from datetime import datetime
from typing import Annotated

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

from app.api.deps import (
    CurrentUserContext,
    get_current_user,
    get_db,
    require_platform_admin_user,
)
from app.schemas.commercial_billing import (
    CommercialAdminEventRead,
    CommercialBillingPeriodRead,
    CommercialBillingPeriodTenantRead,
)
from app.services.commercial_access_policy import (
    CommercialAccessPolicy,
    CommercialPermissionError,
)
from app.services.commercial_billing_periods import CommercialBillingPeriodService
from app.services.commercial_queries import CommercialQueryService

router = APIRouter(prefix="/commercial")
DbSession = Annotated[Session, Depends(get_db)]
CurrentUser = Annotated[CurrentUserContext, Depends(get_current_user)]
PlatformAdmin = Annotated[CurrentUserContext, Depends(require_platform_admin_user)]


@router.get(
    "/billing-periods",
    response_model=list[CommercialBillingPeriodTenantRead],
    summary="读取当前租户不可变账期历史",
)
def list_current_tenant_billing_periods(
    db: DbSession,
    current_user: CurrentUser,
    subscription_id: str | None = None,
    as_of: datetime | None = None,
    limit: int = Query(default=200, ge=1, le=500),
    offset: int = Query(default=0, ge=0),
) -> list[CommercialBillingPeriodTenantRead]:
    try:
        tenant_id = CommercialAccessPolicy.require_account_read(current_user)
        rows = _period_reads(
            db,
            tenant_id,
            subscription_id=subscription_id,
            as_of=as_of,
            limit=limit,
            offset=offset,
        )
        return [CommercialBillingPeriodTenantRead.model_validate(row.model_dump()) for row in rows]
    except CommercialPermissionError as error:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(error)) from error


@router.get(
    "/admin/tenants/{tenant_id}/billing-periods",
    response_model=list[CommercialBillingPeriodRead],
    summary="平台管理员读取租户不可变账期历史",
)
def list_tenant_billing_periods(
    tenant_id: str,
    db: DbSession,
    current_user: PlatformAdmin,
    subscription_id: str | None = None,
    as_of: datetime | None = None,
    limit: int = Query(default=200, ge=1, le=500),
    offset: int = Query(default=0, ge=0),
) -> list[CommercialBillingPeriodRead]:
    target = CommercialAccessPolicy.require_platform_admin(
        current_user,
        target_tenant_id=tenant_id,
    )
    return _period_reads(
        db,
        target,
        subscription_id=subscription_id,
        as_of=as_of,
        limit=limit,
        offset=offset,
    )


@router.get(
    "/admin/tenants/{tenant_id}/admin-events",
    response_model=list[CommercialAdminEventRead],
    summary="平台管理员读取商业配置与续期审计",
)
def list_tenant_commercial_admin_events(
    tenant_id: str,
    db: DbSession,
    current_user: PlatformAdmin,
    action: str | None = None,
    resource_type: str | None = None,
    resource_id: str | None = None,
    start: datetime | None = None,
    end: datetime | None = None,
    limit: int = Query(default=200, ge=1, le=500),
    offset: int = Query(default=0, ge=0),
) -> list[CommercialAdminEventRead]:
    target = CommercialAccessPolicy.require_platform_admin(
        current_user,
        target_tenant_id=tenant_id,
    )
    try:
        return CommercialQueryService(db).list_admin_events(
            target,
            action=action,
            resource_type=resource_type,
            resource_id=resource_id,
            start=start,
            end=end,
            limit=limit,
            offset=offset,
        )
    except ValueError as error:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(error)) from error


def _period_reads(
    db: Session,
    tenant_id: str,
    *,
    subscription_id: str | None,
    as_of: datetime | None,
    limit: int,
    offset: int,
) -> list[CommercialBillingPeriodRead]:
    rows = CommercialQueryService(db).list_billing_periods(
        tenant_id,
        subscription_id=subscription_id,
        limit=limit,
        offset=offset,
    )
    return [CommercialBillingPeriodService.to_read(row, as_of=as_of) for row in rows]
