"""Pydantic schemas for Communication APIs."""
from __future__ import annotations

from datetime import datetime
from decimal import Decimal
from typing import Any
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field


class ORMModel(BaseModel):
    model_config = ConfigDict(from_attributes=True)


class ProviderCreate(BaseModel):
    name: str
    provider_kind: str
    channel: str
    priority: int = 100
    credentials: dict[str, Any] | None = None
    settings: dict[str, Any] | None = None
    balance: Decimal | None = None
    rate_limit_per_minute: int | None = None
    max_retries: int = 3
    is_default: bool = False


class ProviderUpdate(BaseModel):
    name: str | None = None
    priority: int | None = None
    credentials: dict[str, Any] | None = None
    settings: dict[str, Any] | None = None
    balance: Decimal | None = None
    rate_limit_per_minute: int | None = None
    max_retries: int | None = None
    status: str | None = None
    is_default: bool | None = None


class ProviderOut(ORMModel):
    id: UUID
    tenant_id: UUID
    name: str
    provider_kind: str
    channel: str
    status: str
    priority: int
    balance: Decimal | None = None
    rate_limit_per_minute: int | None = None
    max_retries: int
    circuit_state: str
    consecutive_failures: int
    last_health_at: datetime | None = None
    last_error: str | None = None
    is_default: bool
    created_at: datetime
    updated_at: datetime


class SenderCreate(BaseModel):
    channel: str
    value: str
    label: str | None = None
    provider_config_id: UUID | None = None
    is_default: bool = False
    is_active: bool = True


class SenderOut(ORMModel):
    id: UUID
    tenant_id: UUID
    channel: str
    value: str
    label: str | None = None
    provider_config_id: UUID | None = None
    is_default: bool
    is_active: bool
    created_at: datetime


class TemplateCreate(BaseModel):
    template_key: str
    name: str
    channel: str
    locale: str = "fa"
    body: str
    subject: str | None = None
    variables: list[str] | None = None


class TemplateOut(ORMModel):
    id: UUID
    tenant_id: UUID
    template_key: str
    name: str
    channel: str
    locale: str
    version: int
    status: str
    body: str
    subject: str | None = None
    variables: list[str] | None = None
    approved_by: str | None = None
    approved_at: datetime | None = None
    rejection_reason: str | None = None
    created_at: datetime


class TemplatePreviewRequest(BaseModel):
    variables: dict[str, Any] = Field(default_factory=dict)


class TemplatePreviewResponse(BaseModel):
    rendered: str
    subject: str | None = None


class ContactCreate(BaseModel):
    display_name: str | None = None
    phone: str | None = None
    email: str | None = None
    push_token: str | None = None
    metadata_json: dict[str, Any] | None = None
    tags: list[str] | None = None


class ContactOut(ORMModel):
    id: UUID
    tenant_id: UUID
    display_name: str | None = None
    phone: str | None = None
    email: str | None = None
    push_token: str | None = None
    metadata_json: dict[str, Any] | None = None
    tags: list[str] | None = None
    created_at: datetime


class ContactSourceCreate(BaseModel):
    name: str
    source_type: str
    base_url: str | None = None
    endpoint_path: str | None = None
    auth_config: dict[str, Any] | None = None
    query_mapping: dict[str, Any] | None = None
    field_mapping: dict[str, Any] | None = None
    is_active: bool = True


class ContactSourceOut(ORMModel):
    id: UUID
    tenant_id: UUID
    name: str
    source_type: str
    base_url: str | None = None
    endpoint_path: str | None = None
    field_mapping: dict[str, Any] | None = None
    is_active: bool
    created_at: datetime


class MessageSendRequest(BaseModel):
    channel: str = "sms"
    to_address: str | None = None
    from_address: str | None = None
    body: str | None = None
    subject: str | None = None
    template_key: str | None = None
    template_id: UUID | None = None
    template_variables: dict[str, Any] | None = None
    priority: str = "normal"
    scheduled_at: datetime | None = None
    correlation_id: str | None = None
    source_module: str | None = None
    metadata_json: dict[str, Any] | None = None
    contact_source_id: UUID | None = None
    contact_query: dict[str, Any] | None = None
    batch: bool = False
    process_immediately: bool = True


class MessageOut(ORMModel):
    id: UUID
    tenant_id: UUID
    channel: str
    status: str
    to_address: str
    from_address: str | None = None
    subject: str | None = None
    body: str
    template_key: str | None = None
    provider_config_id: UUID | None = None
    provider_message_id: str | None = None
    priority: str
    scheduled_at: datetime | None = None
    sent_at: datetime | None = None
    delivered_at: datetime | None = None
    failed_at: datetime | None = None
    error_code: str | None = None
    error_message: str | None = None
    retry_count: int
    correlation_id: str | None = None
    source_module: str | None = None
    created_at: datetime


class DeliveryEventOut(ORMModel):
    id: UUID
    message_id: UUID
    status: str
    provider_config_id: UUID | None = None
    detail: str | None = None
    payload: dict[str, Any] | None = None
    created_at: datetime


class QueueItemOut(ORMModel):
    id: UUID
    message_id: UUID
    status: str
    priority: str
    attempt: int
    max_attempts: int
    available_at: datetime
    is_dead_letter: bool
    last_error: str | None = None
    batch_id: str | None = None
    created_at: datetime


class OTPRequest(BaseModel):
    destination: str
    channel: str = "sms"
    purpose: str | None = None
    ttl_seconds: int | None = None
    code_length: int = 6


class OTPRequestOut(BaseModel):
    challenge_id: UUID
    destination: str
    channel: str
    expires_at: datetime
    message_id: UUID | None = None
    # Returned only in non-production for tests/dev
    debug_code: str | None = None


class OTPVerifyRequest(BaseModel):
    destination: str
    code: str
    challenge_id: UUID | None = None


class OTPVerifyOut(BaseModel):
    verified: bool
    challenge_id: UUID | None = None
    status: str


class WebhookIn(BaseModel):
    provider_kind: str
    event_type: str
    external_id: str | None = None
    message_id: UUID | None = None
    payload: dict[str, Any] | None = None
    signature: str | None = None


class WebhookOut(ORMModel):
    id: UUID
    provider_kind: str
    event_type: str
    external_id: str | None = None
    message_id: UUID | None = None
    signature_valid: bool
    processed: bool
    created_at: datetime


class CapabilitiesOut(BaseModel):
    service: str
    version: str
    channels: list[dict[str, Any]]
    features: list[str]
    independent: bool = True
    requires_other_modules: bool = False


class ProviderStatusOut(BaseModel):
    id: UUID
    name: str
    provider_kind: str
    channel: str
    status: str
    circuit_state: str
    consecutive_failures: int
    balance: Decimal | None = None
    rate_limit_per_minute: int | None = None
    last_health_at: datetime | None = None
    last_error: str | None = None
    healthy: bool


class MonitoringStatsOut(BaseModel):
    messages_by_status: dict[str, int]
    queue_by_status: dict[str, int]
    providers: list[ProviderStatusOut]
    rate_limit_deferrals: int = 0
    checked_at: str | None = None
