"""Admin domain - Pydantic schemas."""
from __future__ import annotations

from datetime import datetime
from typing import Literal, Optional
from uuid import UUID

from pydantic import BaseModel, EmailStr, Field, model_validator

from src.domain.billing.schemas import PlanOfferPublic


class PlanFeatures(BaseModel):
    max_projects: Optional[int] = None
    max_codegen_runs_per_month: Optional[int] = None
    max_preview_environments: Optional[int] = None
    max_team_members: Optional[int] = None
    custom_domains: bool = False
    priority_support: bool = False


class PlanLimits(BaseModel):
    ai_tokens_per_month: Optional[int] = None
    build_minutes_per_month: Optional[int] = None
    preview_minutes_per_month: Optional[int] = None
    storage_gb: Optional[int] = None


class SubscriptionPlanCreate(BaseModel):
    name: str
    slug: str
    description: Optional[str] = None
    price_monthly: int
    price_yearly: Optional[int] = None
    currency: str = "usd"
    features: Optional[PlanFeatures] = None
    limits: Optional[PlanLimits] = None
    sort_order: int = 0
    trial_days: int = 0
    includes_metered_billing: bool = False
    metered_unit_label: Optional[str] = None


class SubscriptionPlanUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    price_monthly: Optional[int] = None
    price_yearly: Optional[int] = None
    is_active: Optional[bool] = None
    features: Optional[PlanFeatures] = None
    limits: Optional[PlanLimits] = None
    sort_order: Optional[int] = None
    trial_days: Optional[int] = None
    includes_metered_billing: Optional[bool] = None
    metered_unit_label: Optional[str] = None


YearlyPriceSource = Literal["catalog", "estimated_monthly_x12"]


class SubscriptionPlanResponse(BaseModel):
    id: UUID
    name: str
    slug: str
    description: Optional[str]
    is_active: bool
    price_monthly: Optional[int] = None
    price_yearly: Optional[int] = None
    yearly_price_source: Optional[YearlyPriceSource] = None
    currency: str
    stripe_product_id: Optional[str]
    stripe_monthly_price_id: Optional[str]
    stripe_yearly_price_id: Optional[str]
    features: Optional[dict]
    limits: Optional[dict]
    sort_order: int
    trial_days: int
    custom_pricing: bool = False
    offer: Optional[PlanOfferPublic] = None
    includes_metered_billing: bool
    metered_stripe_price_id: Optional[str]
    metered_unit_label: Optional[str]
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


# --- Platform admin console ---


class AdminUserListItem(BaseModel):
    id: UUID
    email: str
    display_name: Optional[str] = None
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    created_at: datetime
    email_verified: bool
    is_platform_admin: bool
    is_paying_customer: bool = False
    subscribed_plans: list[str] = Field(default_factory=list)

    model_config = {"from_attributes": False}


class AdminUserListResponse(BaseModel):
    items: list[AdminUserListItem]
    total: int
    limit: int
    offset: int


class AdminEmailComposerOptions(BaseModel):
    from_addresses: list[EmailStr]


class AdminEmailSendRequest(BaseModel):
    user_ids: list[UUID] = Field(min_length=1, max_length=200)
    from_email: EmailStr
    subject: str = Field(min_length=1, max_length=200)
    html_body: str = Field(min_length=1, max_length=100_000)
    scheduled_at: Optional[datetime] = None

    @model_validator(mode="after")
    def unique_recipients(self) -> "AdminEmailSendRequest":
        if len(set(self.user_ids)) != len(self.user_ids):
            raise ValueError("Recipients must be unique")
        return self


class AdminEmailSendResponse(BaseModel):
    recipient_count: int
    scheduled_at: Optional[datetime] = None


class CreatePlatformAdminBody(BaseModel):
    """Either reference an existing ``users`` row (``user_id``) or create one from ``email``."""

    user_id: Optional[UUID] = None
    email: Optional[EmailStr] = None
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    phone: Optional[str] = None
    company: Optional[str] = None

    @model_validator(mode="after")
    def xor_user_or_email(self) -> "CreatePlatformAdminBody":
        if self.user_id is not None and self.email is not None:
            raise ValueError("Provide exactly one of user_id or email")
        if self.user_id is None and self.email is None:
            raise ValueError("Provide user_id or email")
        return self


class CreatePlatformAdminResponse(BaseModel):
    user_id: UUID
    email: str
    created_new_user: bool
    created_admin_record: bool
