"""Telegram account + channel Pydantic schemas.

Uses repo_core base classes:
    - ``BaseRequestSchema`` — inbound (extra="forbid")
    - ``BaseResponseSchema`` — outbound (from_attributes=True)
    - ``BasePatchSchema`` — partial updates
"""

from __future__ import annotations

import uuid
from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field, field_validator

from repo_core.base.schemas import BaseRequestSchema, BaseResponseSchema, BasePatchSchema


# -- Account CRUD ----------------------------------------------------------

class AccountCreateRequest(BaseRequestSchema):
    """Payload for creating a Telegram account."""
    platform: str = Field(default="telegram")
    phone_number: str = Field(..., min_length=1, max_length=32)
    external_id: str | None = None
    username: str | None = None
    display_name: str | None = None
    session: str = Field(..., min_length=1)
    metadata: dict[str, Any] = Field(default_factory=dict)


class AccountResponse(BaseResponseSchema):
    """Telegram account API response."""
    id: uuid.UUID
    phone_number: str
    external_id: str | None = None
    username: str | None = None
    display_name: str | None = None
    platform: str = "telegram"
    account_type: str = "crawler"
    account_metadata: dict[str, Any] = Field(default_factory=dict)
    is_active: bool = True
    status: str = "active"
    flood_wait_until: datetime | None = None
    last_active_at: datetime | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class AccountListResponse(BaseModel):
    items: list[AccountResponse]
    total: int
    limit: int
    offset: int


class AccountMetadataUpdateRequest(BaseRequestSchema):
    metadata: dict[str, Any]


class AccountProfileUpdateRequest(BasePatchSchema):
    """Partial update for account profile fields (username, display_name, phone, account_type)."""
    username: str | None = None
    display_name: str | None = None
    phone_number: str | None = None
    account_type: str | None = None

    @field_validator("account_type")
    @classmethod
    def _validate_account_type(cls, v: str | None) -> str | None:
        if v is not None and v not in ("crawler", "downloader", "manager"):
            raise ValueError(
                f"Invalid account_type '{v}'. "
                f"Must be one of: crawler, downloader, manager"
            )
        return v


class PlatformManagerUpdateRequest(BaseRequestSchema):
    """Set or unset an account as the platform manager for channel orchestration.

    Set ``account_type`` to ``"manager"`` to designate, or to any other
    valid type (``"crawler"``, ``"downloader"``) to unset.
    """
    account_type: str


class AccountStatusUpdateRequest(BaseRequestSchema):
    status: str
    flood_wait_until: datetime | None = None


class SessionResponse(BaseResponseSchema):
    account_id: uuid.UUID
    session: str


class AccountHealthResponse(BaseResponseSchema):
    account_id: uuid.UUID
    platform: str
    status: str
    flood_wait_until: datetime | None = None
    last_active_at: datetime | None = None
    last_checked_at: datetime | None = None
    error_type: str | None = None
    error_category: str | None = None
    phase: str | None = None
    reason: str | None = None
    source: str | None = None


# -- Channel operations ----------------------------------------------------

class TelegramChannelInput(BaseRequestSchema):
    channel: str = Field(..., min_length=1)


class TelegramReactionDetailResponse(BaseModel):
    reaction: str
    count: int


class TelegramRecentPostResponse(BaseModel):
    message_id: int
    date: datetime | None = None
    edit_date: datetime | None = None
    text: str | None = None
    post_author: str | None = None
    grouped_id: int | None = None
    views: int | None = None
    forwards: int | None = None
    comments: int | None = None
    reactions: int | None = None
    media_kind: str | None = None
    media_mime_type: str | None = None
    media_base64: str | None = None
    media_width: int | None = None
    media_height: int | None = None
    media_duration_seconds: float | None = None
    reaction_details: list[TelegramReactionDetailResponse] = Field(default_factory=list)


class TelegramChannelPreviewResponse(BaseModel):
    account_id: uuid.UUID
    channel: str
    resolved_channel_id: int | None = None
    kind: str
    title: str
    username: str | None = None
    description: str | None = None
    member_count: int | None = None
    profile_photo_base64: str | None = None
    linked_chat_id: int | None = None
    admins_count: int | None = None
    online_count: int | None = None
    slowmode_seconds: int | None = None
    can_view_participants: bool | None = None
    can_set_username: bool | None = None
    verified: bool | None = None
    restricted: bool | None = None
    scam: bool | None = None
    fake: bool | None = None
    broadcast: bool | None = None
    megagroup: bool | None = None
    avg_views_last_10: float | None = None
    avg_reactions_last_10: float | None = None
    avg_comments_last_10: float | None = None
    total_posts_analyzed: int = 0
    recent_posts: list[TelegramRecentPostResponse] = Field(default_factory=list)


class TelegramJoinResponse(BaseModel):
    account_id: uuid.UUID
    channel: str
    status: str
    title: str | None = None


class TelegramLeaveResponse(BaseModel):
    account_id: uuid.UUID
    channel: str
    status: str


class TelegramChannelInfo(BaseModel):
    channel_id: int
    title: str
    username: str | None = None
    kind: str
    member_count: int | None = None
    profile_photo_base64: str | None = None
    saved_preview_at: datetime | None = None
    saved_preview: dict[str, Any] | None = None


class TelegramChannelListResponse(BaseModel):
    account_id: uuid.UUID
    items: list[TelegramChannelInfo]
    total: int = 0
    offset: int = 0
    limit: int = 50


# -- Global (cross-account) channel schemas -----------------------------------

class AssignedAccountInfo(BaseModel):
    """Minimal account info shown in channel assignment lists."""
    account_id: str
    phone_number: str = ""
    username: str | None = None
    status: str = "unknown"
    account_type: str = "crawler"


class GlobalChannelInfo(BaseModel):
    """Channel info with assignment data, used by the global /channels API."""
    channel_id: int
    title: str
    username: str | None = None
    kind: str
    member_count: int | None = None
    profile_photo_base64: str | None = None
    saved_preview_at: str | None = None
    saved_preview: dict[str, Any] | None = None
    assigned_accounts: list[AssignedAccountInfo] = Field(default_factory=list)
    assigned_count: int = 0


class GlobalChannelListResponse(BaseModel):
    items: list[GlobalChannelInfo]
    total: int
    offset: int
    limit: int


class GlobalChannelDetailResponse(BaseModel):
    channel_id: int
    title: str
    username: str | None = None
    kind: str
    member_count: int | None = None
    profile_photo_base64: str | None = None
    saved_preview_at: str | None = None
    saved_preview: dict[str, Any] | None = None
    assigned_accounts: list[AssignedAccountInfo] = Field(default_factory=list)


class AccountLeaveResult(BaseModel):
    account_id: str
    status: str


class GlobalChannelDeleteResponse(BaseModel):
    channel_id: str
    title: str | None = None
    accounts_processed: int
    results: list[AccountLeaveResult]
