# @File: backend/schemas/bizmail.py
# @Desc: Pydantic request/response models for Bizmail360 Reseller Manager.
from __future__ import annotations

from datetime import datetime
from typing import List, Optional

from pydantic import BaseModel, ConfigDict, Field


# ---------- Plans ----------
class BizmailPlanBase(BaseModel):
    slug: str = Field(..., min_length=1, max_length=64)
    name: str = Field(..., min_length=1, max_length=128)
    description: Optional[str] = None
    price_monthly: Optional[str] = None
    price_yearly: Optional[str] = None
    currency: str = "USD"
    mailbox_quota: int = 5
    storage_mb_per_mailbox: int = 1024
    aliases_included: int = 20
    features: Optional[str] = None
    is_active: bool = True
    is_featured: bool = False
    sort_order: int = 0


class BizmailPlanCreate(BizmailPlanBase):
    pass


class BizmailPlanUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    price_monthly: Optional[str] = None
    price_yearly: Optional[str] = None
    currency: Optional[str] = None
    mailbox_quota: Optional[int] = None
    storage_mb_per_mailbox: Optional[int] = None
    aliases_included: Optional[int] = None
    features: Optional[str] = None
    is_active: Optional[bool] = None
    is_featured: Optional[bool] = None
    sort_order: Optional[int] = None


class BizmailPlanOut(BizmailPlanBase):
    model_config = ConfigDict(from_attributes=True)
    id: int
    created_at: datetime
    updated_at: datetime


# ---------- Subscriptions ----------
class BizmailSubscriptionCreate(BaseModel):
    plan_id: int
    domain_name: str = Field(..., min_length=3, max_length=255)
    billing_cycle: str = Field("monthly", pattern="^(monthly|yearly)$")


class BizmailSubscriptionOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: int
    user_id: str
    user_email: Optional[str] = None
    plan_id: int
    domain_name: str
    smartermail_domain_ref: Optional[str] = None
    status: str
    billing_cycle: str
    primary_mailbox: Optional[str] = None
    provisioned_at: Optional[datetime] = None
    activated_at: Optional[datetime] = None
    suspended_at: Optional[datetime] = None
    cancelled_at: Optional[datetime] = None
    current_period_end: Optional[datetime] = None
    notes: Optional[str] = None
    mailboxes_used: int = 0
    aliases_used: int = 0
    created_at: datetime
    updated_at: datetime


class BizmailSubscriptionDetail(BizmailSubscriptionOut):
    """Subscription + denormalised plan data for the client dashboard."""

    plan: Optional[BizmailPlanOut] = None
    mailbox_quota: Optional[int] = None
    aliases_included: Optional[int] = None
    storage_mb_per_mailbox: Optional[int] = None


class BizmailActivationResult(BaseModel):
    subscription: BizmailSubscriptionDetail
    primary_mailbox: Optional[str] = None
    primary_password: Optional[str] = Field(
        default=None,
        description=(
            "Auto-generated postmaster password; only returned on the first "
            "activation. Store or send to the client securely."
        ),
    )


class BizmailSubscriptionActionResult(BaseModel):
    subscription: BizmailSubscriptionDetail
    message: str


# ---------- Mailboxes ----------
class BizmailMailboxCreate(BaseModel):
    username: str = Field(..., min_length=1, max_length=64, description="Local-part only (before @)")
    password: str = Field(..., min_length=6, max_length=128)
    display_name: Optional[str] = None
    is_domain_admin: bool = False


class BizmailMailboxUpdate(BaseModel):
    display_name: Optional[str] = None
    disabled: Optional[bool] = None


class BizmailMailboxPasswordReset(BaseModel):
    new_password: str = Field(..., min_length=6, max_length=128)


class BizmailMailboxOut(BaseModel):
    username: str
    display_name: Optional[str] = None
    is_domain_admin: bool = False
    disabled: bool = False
    storage_mb: Optional[int] = None


# ---------- Aliases ----------
class BizmailAliasCreate(BaseModel):
    alias_name: str = Field(..., min_length=1, max_length=64, description="Local-part only (before @)")
    targets: List[str] = Field(..., min_length=1)


class BizmailAliasOut(BaseModel):
    name: str
    addresses: List[str] = []


# ---------- Forwards ----------
class BizmailForwardingUpdate(BaseModel):
    forward_to: str = Field(
        "",
        max_length=255,
        description="Destination address — empty string disables forwarding.",
    )


class BizmailForwardingOut(BaseModel):
    username: str
    forward_to: str = ""
    enabled: bool = False


# ---------- Usage ----------
class BizmailUsageOut(BaseModel):
    mailboxes_used: int = 0
    mailbox_quota: int = 0
    aliases_used: int = 0
    aliases_included: int = 0
    storage_used_mb: int = 0
    storage_quota_mb: int = 0
    degraded: bool = False
    message: Optional[str] = None


# ---------- Admin ----------
class BizmailIntegrationTestResult(BaseModel):
    ok: bool
    message: str
    latency_ms: Optional[int] = None


class BizmailAuditLogOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: int
    subscription_id: Optional[int] = None
    actor_user_id: Optional[str] = None
    actor_email: Optional[str] = None
    action: str
    target: Optional[str] = None
    status: str
    error_message: Optional[str] = None
    created_at: datetime