"""平台商业配置与事实账本的租户安全查询。"""

from __future__ import annotations

from datetime import datetime

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models.commercial import (
    CommercialCostEvent,
    CommercialEntitlement,
    TenantCommercialPlan,
    TenantSubscription,
    UsageMeterEvent,
)
from app.models.commercial_billing import CommercialAdminEvent, CommercialBillingPeriod
from app.services.commercial_access_policy import CommercialAccessPolicy


class CommercialQueryService:
    def __init__(self, db: Session) -> None:
        self.db = db

    def list_plans(
        self,
        tenant_id: str,
        *,
        status: str | None = None,
        limit: int = 100,
        offset: int = 0,
    ) -> list[TenantCommercialPlan]:
        tenant = CommercialAccessPolicy.normalized_tenant_id(tenant_id)
        statement = select(TenantCommercialPlan).where(TenantCommercialPlan.tenant_id == tenant)
        if status:
            statement = statement.where(TenantCommercialPlan.status == status)
        return list(
            self.db.scalars(
                statement.order_by(
                    TenantCommercialPlan.created_at.desc(),
                    TenantCommercialPlan.id.desc(),
                )
                .offset(offset)
                .limit(limit)
            ).all()
        )

    def list_subscriptions(
        self,
        tenant_id: str,
        *,
        status: str | None = None,
        limit: int = 100,
        offset: int = 0,
    ) -> list[TenantSubscription]:
        tenant = CommercialAccessPolicy.normalized_tenant_id(tenant_id)
        statement = select(TenantSubscription).where(TenantSubscription.tenant_id == tenant)
        if status:
            statement = statement.where(TenantSubscription.status == status)
        return list(
            self.db.scalars(
                statement.order_by(
                    TenantSubscription.created_at.desc(),
                    TenantSubscription.id.desc(),
                )
                .offset(offset)
                .limit(limit)
            ).all()
        )

    def list_entitlements(
        self,
        tenant_id: str,
        *,
        subscription_id: str | None = None,
        billing_period_id: str | None = None,
        status: str | None = None,
        limit: int = 200,
        offset: int = 0,
    ) -> list[CommercialEntitlement]:
        tenant = CommercialAccessPolicy.normalized_tenant_id(tenant_id)
        statement = select(CommercialEntitlement).where(CommercialEntitlement.tenant_id == tenant)
        if subscription_id:
            statement = statement.where(CommercialEntitlement.subscription_id == subscription_id)
        if billing_period_id:
            period = self._billing_period(tenant, billing_period_id)
            if period is None:
                raise LookupError("商业账期不存在。")
            if subscription_id and period.subscription_id != subscription_id:
                return []
            statement = statement.where(
                CommercialEntitlement.subscription_id == period.subscription_id,
                CommercialEntitlement.effective_from < period.period_end,
                (
                    CommercialEntitlement.effective_to.is_(None)
                    | (CommercialEntitlement.effective_to > period.period_start)
                ),
            )
        if status:
            statement = statement.where(CommercialEntitlement.status == status)
        return list(
            self.db.scalars(
                statement.order_by(
                    CommercialEntitlement.created_at.desc(),
                    CommercialEntitlement.id.desc(),
                )
                .offset(offset)
                .limit(limit)
            ).all()
        )

    def list_usage_events(
        self,
        tenant_id: str,
        *,
        subscription_id: str | None = None,
        billing_period_id: str | None = None,
        start: datetime | None = None,
        end: datetime | None = None,
        limit: int = 200,
        offset: int = 0,
    ) -> list[UsageMeterEvent]:
        tenant = CommercialAccessPolicy.normalized_tenant_id(tenant_id)
        statement = select(UsageMeterEvent).where(UsageMeterEvent.tenant_id == tenant)
        if subscription_id:
            statement = statement.where(UsageMeterEvent.subscription_id == subscription_id)
        if billing_period_id:
            statement = statement.where(UsageMeterEvent.billing_period_id == billing_period_id)
        statement = _window(statement, UsageMeterEvent.occurred_at, start=start, end=end)
        return list(
            self.db.scalars(
                statement.order_by(
                    UsageMeterEvent.occurred_at.desc(),
                    UsageMeterEvent.id.desc(),
                )
                .offset(offset)
                .limit(limit)
            ).all()
        )

    def list_cost_events(
        self,
        tenant_id: str,
        *,
        subscription_id: str | None = None,
        billing_period_id: str | None = None,
        start: datetime | None = None,
        end: datetime | None = None,
        limit: int = 200,
        offset: int = 0,
    ) -> list[CommercialCostEvent]:
        tenant = CommercialAccessPolicy.normalized_tenant_id(tenant_id)
        statement = select(CommercialCostEvent).where(CommercialCostEvent.tenant_id == tenant)
        if subscription_id:
            statement = statement.where(CommercialCostEvent.subscription_id == subscription_id)
        if billing_period_id:
            statement = statement.where(CommercialCostEvent.billing_period_id == billing_period_id)
        statement = _window(statement, CommercialCostEvent.occurred_at, start=start, end=end)
        return list(
            self.db.scalars(
                statement.order_by(
                    CommercialCostEvent.occurred_at.desc(),
                    CommercialCostEvent.id.desc(),
                )
                .offset(offset)
                .limit(limit)
            ).all()
        )

    def list_billing_periods(
        self,
        tenant_id: str,
        *,
        subscription_id: str | None = None,
        limit: int = 200,
        offset: int = 0,
    ) -> list[CommercialBillingPeriod]:
        tenant = CommercialAccessPolicy.normalized_tenant_id(tenant_id)
        statement = select(CommercialBillingPeriod).where(
            CommercialBillingPeriod.tenant_id == tenant
        )
        if subscription_id:
            statement = statement.where(CommercialBillingPeriod.subscription_id == subscription_id)
        return list(
            self.db.scalars(
                statement.order_by(
                    CommercialBillingPeriod.period_start.desc(),
                    CommercialBillingPeriod.id.desc(),
                )
                .offset(offset)
                .limit(limit)
            ).all()
        )

    def list_admin_events(
        self,
        tenant_id: str,
        *,
        action: str | None = None,
        resource_type: str | None = None,
        resource_id: str | None = None,
        start: datetime | None = None,
        end: datetime | None = None,
        limit: int = 200,
        offset: int = 0,
    ) -> list[CommercialAdminEvent]:
        tenant = CommercialAccessPolicy.normalized_tenant_id(tenant_id)
        statement = select(CommercialAdminEvent).where(CommercialAdminEvent.tenant_id == tenant)
        if action:
            statement = statement.where(CommercialAdminEvent.action == action)
        if resource_type:
            statement = statement.where(CommercialAdminEvent.resource_type == resource_type)
        if resource_id:
            statement = statement.where(CommercialAdminEvent.resource_id == resource_id)
        statement = _window(
            statement,
            CommercialAdminEvent.occurred_at,
            start=start,
            end=end,
        )
        return list(
            self.db.scalars(
                statement.order_by(
                    CommercialAdminEvent.occurred_at.desc(),
                    CommercialAdminEvent.id.desc(),
                )
                .offset(offset)
                .limit(limit)
            ).all()
        )

    def _billing_period(
        self,
        tenant_id: str,
        billing_period_id: str,
    ) -> CommercialBillingPeriod | None:
        return self.db.scalar(
            select(CommercialBillingPeriod).where(
                CommercialBillingPeriod.tenant_id == tenant_id,
                CommercialBillingPeriod.id == billing_period_id,
            )
        )


def _window(statement, column, *, start: datetime | None, end: datetime | None):
    if start is not None:
        _require_aware(start)
        statement = statement.where(column >= start)
    if end is not None:
        _require_aware(end)
        statement = statement.where(column < end)
    if start is not None and end is not None and end <= start:
        raise ValueError("商业事实查询结束时间必须晚于开始时间。")
    return statement


def _require_aware(value: datetime) -> None:
    if value.tzinfo is None or value.utcoffset() is None:
        raise ValueError("商业事实查询时间必须显式包含时区。")
