from __future__ import annotations

from datetime import datetime
from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field


class TradeContextResponse(BaseModel):
    requested_date: str
    actual_date: str | None
    previous_date: str | None
    observed_at: datetime | None
    state: str | None
    carried_forward: bool
    message: str


class MarketSummaryResponse(BaseModel):
    context: TradeContextResponse
    values: dict[str, Any] | None


class SearchResultResponse(BaseModel):
    entity_type: Literal["stock", "sector", "theme", "index"]
    identifier: str
    code: str
    name: str
    sector: str | None


class SearchGroupResponse(BaseModel):
    entity_type: Literal["stock", "sector", "theme", "index"]
    label: str
    items: list[SearchResultResponse]


class SearchResponse(BaseModel):
    query: str
    groups: list[SearchGroupResponse]


class ChartPointResponse(BaseModel):
    time: str
    open: float
    high: float
    low: float
    close: float
    volume: float
    amount: float
    average: float | None


class ChartResponse(BaseModel):
    entity_type: str
    identifier: str
    code: str
    name: str
    interval: Literal["day", "minute"]
    trade_date: str
    observed_at: datetime
    previous_close: float | None
    range_start: str | None
    range_end: str | None
    points: list[ChartPointResponse]


class EntityDetailResponse(BaseModel):
    model_config = ConfigDict(extra="allow")

    entity: SearchResultResponse
    trade_date: str
    observed_at: datetime
    price: float
    previous_close: float | None
    change: float | None
    metrics: list[dict[str, Any]] = Field(default_factory=list)
    money_flow: dict[str, Any] | None = None
    event: dict[str, Any] | None = None


class ReferenceSyncResponse(BaseModel):
    calendar_days: int = Field(ge=1)
    entities: int = Field(ge=1)
    observed_at: datetime


class SnapshotSyncResponse(BaseModel):
    trade_date: str
    observed_at: datetime
    coverage: float
    stocks: int
    limit_up: int
    limit_down: int
    broken: int
    temperature: int


class MarketWorkspaceResponse(BaseModel):
    trade_date: str | None
    observed_at: datetime | None = None
    carried_forward: bool = False
    message: str = ""
    overview: dict[str, Any] = Field(default_factory=dict)
    sentiment: dict[str, Any] | None = None
    history: list[dict[str, Any]] | None = None
    items: list[dict[str, Any]] | None = None


class RotationMembersResponse(BaseModel):
    trade_date: str
    sector_name: str
    sector_code: str
    member_count: int = Field(ge=0)
    quoted_count: int = Field(ge=0)
    coverage: float = Field(ge=0, le=1)
    items: list[dict[str, Any]] = Field(default_factory=list)


class MarketInsightResponse(BaseModel):
    model_config = ConfigDict(extra="allow")

    requested_date: str
    trade_date: str
    observed_at: datetime | None = None
    state: str | None = None
    carried_forward: bool = False
    message: str = ""
    summary: dict[str, Any] = Field(default_factory=dict)


class ThemeDetailResponse(BaseModel):
    model_config = ConfigDict(extra="allow")

    trade_date: str
    observed_at: datetime | None = None
    state: str | None = None
    message: str = ""
    theme: dict[str, Any]
    summary: dict[str, Any]
    members: list[dict[str, Any]]


class SeatAliasRequest(BaseModel):
    seat_name: str = Field(min_length=1, max_length=200)
    alias_name: str = Field(min_length=1, max_length=80)


class SeatAliasResponse(BaseModel):
    seat_name: str
    alias_name: str
