from typing import Annotated, Optional, Dict, List, Union, Any

from pydantic import BaseModel, Discriminator, Field, RootModel, Tag

from app.schemas.common import JsonData
from app.schemas.music import MusicInfo, MusicMeta
from app.schemas.media import OptionalMediaIdentityMixin
from app.schemas.types import MediaSource


class MetaInfo(OptionalMediaIdentityMixin, BaseModel):
    """
    识别元数据
    """
    # 是否处理的文件
    isfile: Optional[bool] = False
    # 原字符串
    org_string: Optional[str] = None
    # 原标题
    title: Optional[str] = None
    # 副标题
    subtitle: Optional[str] = None
    # 类型 电影、电视剧、音乐
    type: Optional[str] = None
    # 名称
    name: Optional[str] = None
    # 识别的中文名
    cn_name: Optional[str] = None
    # 识别的英文名
    en_name: Optional[str] = None
    # 年份
    year: Optional[str] = None
    # 总季数
    total_season: Optional[int] = 0
    # 识别的开始季 数字
    begin_season: Optional[int] = None
    # 识别的结束季 数字
    end_season: Optional[int] = None
    # 总集数
    total_episode: Optional[int] = 0
    # 识别的开始集
    begin_episode: Optional[int] = None
    # 识别的结束集
    end_episode: Optional[int] = None
    # SxxExx
    season_episode: Optional[str] = None
    # 集列表
    episode_list: Optional[List[int]] = Field(default_factory=list)
    # Partx Cd Dvd Disk Disc
    part: Optional[str] = None
    # 识别的资源类型
    resource_type: Optional[str] = None
    # 识别的效果
    resource_effect: Optional[str] = None
    # 识别的分辨率
    resource_pix: Optional[str] = None
    # 识别的制作组/字幕组
    resource_team: Optional[str] = None
    # 视频编码
    video_encode: Optional[str] = None
    # 音频编码
    audio_encode: Optional[str] = None
    # 资源类型
    edition: Optional[str] = None
    # 流媒体平台
    web_source: Optional[str] = None
    # 应用的识别词信息
    apply_words: Optional[List[str]] = None
    # 剧集组
    episode_group: Optional[str] = None
    # 显式媒体数据源
    media_source: Optional[MediaSource] = None
    # 显式媒体数据源原生ID
    media_id: Optional[str] = None


class MediaImageSet(BaseModel):
    """跨媒体源兼容的人物图片尺寸集合。"""

    large: Optional[str] = None
    common: Optional[str] = None
    medium: Optional[str] = None
    normal: Optional[str] = None
    small: Optional[str] = None
    grid: Optional[str] = None


class MediaCredit(BaseModel):
    """影视条目中的演职员摘要。"""

    id: Optional[int | str] = None
    name: Optional[str] = None
    original_name: Optional[str] = None
    character: Optional[str] = None
    type: Optional[str | int] = None
    gender: Optional[str | int] = None
    adult: Optional[bool] = None
    known_for_department: Optional[str] = None
    profile_path: Optional[str] = None
    credit_id: Optional[str] = None
    cast_id: Optional[int] = None
    order: Optional[int] = None
    department: Optional[str] = None
    job: Optional[str] = None
    popularity: Optional[float] = None
    roles: list[str] = Field(default_factory=list)
    title: Optional[str] = None
    url: Optional[str] = None
    uri: Optional[str] = None
    sharing_url: Optional[str] = None
    avatar: Optional[str | MediaImageSet] = None
    images: Optional[MediaImageSet] = None
    latin_name: Optional[str] = None
    career: list[str] = Field(default_factory=list)
    relation: Optional[str] = None
    user: Optional[JsonData] = None


class MediaGenre(BaseModel):
    """影视风格摘要。"""

    id: Optional[int | str] = None
    name: Optional[str] = None


class MediaCompany(BaseModel):
    """电视网或制作公司的标准摘要。"""

    id: Optional[int | str] = None
    name: Optional[str] = None
    logo_path: Optional[str] = None
    origin_country: Optional[str] = None


class MediaCountry(BaseModel):
    """影视制作国家或地区。"""

    id: Optional[int | str] = None
    iso_3166_1: Optional[str] = None
    name: Optional[str] = None


class MediaLanguage(BaseModel):
    """影视内容使用的语言。"""

    english_name: Optional[str] = None
    iso_639_1: Optional[str] = None
    name: Optional[str] = None


class MediaReleaseDate(BaseModel):
    """电影在单个地区的一次发行记录。"""

    date: str
    iso_code: Optional[str] = None
    note: Optional[str] = None
    type: Optional[int] = None


class MediaEpisode(BaseModel):
    """电视剧即将播出的单集摘要。"""

    id: Optional[int] = None
    air_date: Optional[str] = None
    episode_number: Optional[int] = None
    episode_type: Optional[str] = None
    name: Optional[str] = None
    overview: Optional[str] = None
    production_code: Optional[str] = None
    runtime: Optional[int] = None
    season_number: Optional[int] = None
    show_id: Optional[int] = None
    still_path: Optional[str] = None
    vote_average: Optional[float] = None
    vote_count: Optional[int] = None


class MediaSeason(BaseModel):
    """标准季信息以及剧集组季信息。"""

    id: Optional[int | str] = None
    air_date: Optional[str] = None
    episode_count: Optional[int] = None
    name: Optional[str] = None
    overview: Optional[str] = None
    poster_path: Optional[str] = None
    season_number: Optional[int] = None
    vote_average: Optional[float] = None
    order: Optional[int] = None
    locked: Optional[bool] = None
    episodes: list[MediaEpisode] = Field(default_factory=list)


class MediaEpisodeGroupNetwork(BaseModel):
    """TMDB 剧集组所属电视网信息。"""

    id: Optional[int] = None
    name: Optional[str] = None
    logo_path: Optional[str] = None
    origin_country: Optional[str] = None


class MediaEpisodeGroup(BaseModel):
    """TMDB 电视剧的剧集分组摘要。"""

    description: str = ""
    episode_count: int = 0
    group_count: int = 0
    id: str
    name: str
    network: Optional[MediaEpisodeGroupNetwork] = None
    type: int


class MediaInfo(OptionalMediaIdentityMixin, BaseModel):
    """
    识别媒体信息
    """
    # 媒体主身份来源
    media_source: Optional[MediaSource] = None
    # 请求级刮削来源
    scrape_source: Optional[str] = None
    # 类型 电影、电视剧、合集
    type: Optional[str] = None
    # 媒体标题
    title: Optional[str] = None
    # 英文标题
    en_title: Optional[str] = None
    # 香港、台湾、新加坡地区标题
    hk_title: Optional[str] = None
    tw_title: Optional[str] = None
    sg_title: Optional[str] = None
    # 年份
    year: Optional[str] = None
    # 标题（年份）
    title_year: Optional[str] = None
    # 当前指定季，如有
    season: Optional[int] = None
    # 数据源返回的辅助 ID，仅作为元数据输出
    tmdb_id: Optional[int] = None
    imdb_id: Optional[str] = None
    tvdb_id: Optional[int] = None
    tvdb_slug: Optional[str] = None
    douban_id: Optional[str] = None
    bangumi_id: Optional[int] = None
    anilist_id: Optional[int] = None
    anidb_id: Optional[int] = None
    # 合集ID
    collection_id: Optional[int] = None
    # 当前来源原生 ID
    media_id: Optional[str] = None
    # 媒体原语种
    original_language: Optional[str] = None
    # 媒体原发行标题
    original_title: Optional[str] = None
    # 媒体发行日期
    release_date: Optional[str] = None
    # 背景图片
    backdrop_path: Optional[str] = None
    # 海报图片
    poster_path: Optional[str] = None
    # 标题 LOGO
    logo_path: Optional[str] = None
    # 评分
    vote_average: Optional[float] = 0.0
    # 描述
    overview: Optional[str] = None
    # 二级分类
    category: Optional[str] = ""
    # 季季集清单
    seasons: Optional[Dict[int, list[int]]] = Field(default_factory=dict)
    # 季详情
    season_info: Optional[List[MediaSeason]] = Field(default_factory=list)
    # 各季首播年份
    season_years: Optional[Dict[int, str]] = Field(default_factory=dict)
    # 别名和译名
    names: Optional[list[str]] = Field(default_factory=list)
    # 演员
    actors: Optional[list[Union[MediaCredit, str]]] = Field(default_factory=list)
    # 导演
    directors: Optional[list[Union[MediaCredit, str]]] = Field(default_factory=list)
    # 详情链接
    detail_link: Optional[str] = None
    # 其它TMDB属性
    # 是否成人内容
    adult: Optional[bool] = False
    # 创建人
    created_by: Optional[list[MediaCredit]] = Field(default_factory=list)
    # 集时长
    episode_run_time: Optional[list[int]] = Field(default_factory=list)
    # 风格
    genres: Optional[List[MediaGenre]] = Field(default_factory=list)
    # 首播日期
    first_air_date: Optional[str] = None
    # 首页
    homepage: Optional[str] = None
    # 语种
    languages: Optional[list[str]] = Field(default_factory=list)
    # 最后上映日期
    last_air_date: Optional[str] = None
    # 流媒体平台
    networks: Optional[list[MediaCompany]] = Field(default_factory=list)
    # 集数
    number_of_episodes: Optional[int] = 0
    # 季数
    number_of_seasons: Optional[int] = 0
    # 原产国
    origin_country: Optional[list[str]] = Field(default_factory=list)
    # 原名
    original_name: Optional[str] = None
    # 出品公司
    production_companies: Optional[list[MediaCompany]] = Field(default_factory=list)
    # 出品国
    production_countries: Optional[list[MediaCountry]] = Field(default_factory=list)
    # 语种
    spoken_languages: Optional[list[MediaLanguage]] = Field(default_factory=list)
    # 所有发行日期
    release_dates: list[MediaReleaseDate] = Field(default_factory=list)
    # 状态
    status: Optional[str] = None
    # 标签
    tagline: Optional[str] = None
    # 风格ID
    genre_ids: Optional[list[int | str]] = Field(default_factory=list)
    # 评价数量
    vote_count: Optional[int] = 0
    # 流行度
    popularity: Optional[float] = 0.0
    # 时长
    runtime: Optional[int] = None
    # 下一集
    next_episode_to_air: Optional[MediaEpisode] = None
    # 内容分级
    content_rating: Optional[str] = None
    # 全部剧集组
    episode_groups: Optional[list[MediaEpisodeGroup | MediaSeason]] = Field(default_factory=list)
    # 剧集组
    episode_group: Optional[str] = None
    # 各数据源原始信息；Core MediaInfo.to_dict() 保留这些键供兼容调用方使用。
    tmdb_info: Optional[dict[str, JsonData]] = None
    douban_info: Optional[dict[str, JsonData]] = None
    bangumi_info: Optional[dict[str, JsonData]] = None
    anilist_info: Optional[dict[str, JsonData]] = None


class TorrentInfo(OptionalMediaIdentityMixin, BaseModel):
    """
    搜索种子信息
    """
    # 站点ID
    site: Optional[int] = None
    # 站点名称
    site_name: Optional[str] = None
    # 站点Cookie
    site_cookie: Optional[str] = None
    # 站点UA
    site_ua: Optional[str] = None
    # 站点是否使用代理
    site_proxy: Optional[bool] = False
    # 站点优先级
    site_order: Optional[int] = 0
    # 站点下载器
    site_downloader: Optional[str] = None
    # 种子名称
    title: Optional[str] = None
    # 种子副标题
    description: Optional[str] = None
    # 种子页面声明的媒体身份
    media_source: Optional[MediaSource] = None
    media_id: Optional[str] = None
    # 种子链接
    enclosure: Optional[str] = None
    # 详情页面
    page_url: Optional[str] = None
    # 种子大小
    size: Optional[float] = 0.0
    # 做种者
    seeders: Optional[int] = 0
    # 下载者
    peers: Optional[int] = 0
    # 完成者
    grabs: Optional[int] = 0
    # 发布时间
    pubdate: Optional[str] = None
    # 已过时间
    date_elapsed: Optional[str] = None
    # 免费截止时间
    freedate: Optional[str] = None
    # 上传因子
    uploadvolumefactor: Optional[float] = None
    # 下载因子
    downloadvolumefactor: Optional[float] = None
    # HR
    hit_and_run: Optional[bool] = False
    # 种子标签
    labels: Optional[list[str]] = Field(default_factory=list)
    # 种子优先级
    pri_order: Optional[int] = 0
    # 种子分类 电影/电视剧/音乐
    category: Optional[str] = None
    # 促销
    volume_factor: Optional[str] = None
    # 剩余免费时间
    freedate_diff: Optional[str] = None


class SubtitleInfo(BaseModel):
    """
    搜索字幕信息
    """
    # 站点ID
    site: Optional[int] = None
    # 站点名称
    site_name: Optional[str] = None
    # 站点Cookie
    site_cookie: Optional[str] = None
    # 站点UA
    site_ua: Optional[str] = None
    # 站点是否使用代理
    site_proxy: Optional[bool] = False
    # 站点优先级
    site_order: Optional[int] = 0
    # 字幕标题
    title: Optional[str] = None
    # 字幕描述
    description: Optional[str] = None
    # 字幕下载链接
    enclosure: Optional[str] = None
    # 详情页面
    page_url: Optional[str] = None
    # 语言
    language: Optional[str] = None
    # 语言图标
    language_icon: Optional[str] = None
    # 字幕大小
    size: Optional[float] = 0.0
    # 发布时间
    pubdate: Optional[str] = None
    # 已过时间
    date_elapsed: Optional[str] = None
    # 点击/下载次数
    grabs: Optional[int] = 0
    # 上传者
    uploader: Optional[str] = None
    # 举报页面
    report_url: Optional[str] = None
    # 种子ID
    torrent_id: Optional[str] = None
    # 字幕ID
    subtitle_id: Optional[str] = None
    # 下载文件名
    file_name: Optional[str] = None
    # 识别元数据
    meta_info: Optional[MetaInfo] = None
    # SxxExx
    season_episode: Optional[str] = None
    # 集列表
    episode_list: Optional[List[int]] = Field(default_factory=list)


class Context(BaseModel):
    """
    上下文
    """
    # 元数据
    meta_info: Optional[Union[MusicMeta, MetaInfo]] = None
    # 媒体信息
    media_info: Optional[Union[MusicInfo, MediaInfo]] = None
    # 种子信息
    torrent_info: Optional[TorrentInfo] = None
    # 候选资源来源：rss、spider、search、unknown
    resource_source: Optional[str] = "unknown"
    # 候选匹配来源：MediaSource 枚举值、title、unknown
    match_source: Optional[str] = "unknown"
    # 候选自身是否已经识别出有效媒体 ID
    candidate_recognized: Optional[bool] = False
    # 当前 media_info 是否为目标媒体回填
    media_info_is_target: Optional[bool] = False
    # 下载层确认候选资源覆盖完整目标范围，供订阅事实写入判断整包资源
    confirmed_full_coverage: Optional[bool] = False


class MediaPerson(BaseModel):
    """
    媒体人物信息
    """
    # 来源：themoviedb、douban、bangumi、anilist
    source: Optional[str] = None
    # 公共
    id: Optional[int | str] = None
    type: Optional[Union[str, int]] = 1
    name: Optional[str] = None
    character: Optional[str] = None
    images: Optional[MediaImageSet] = None
    # themoviedb
    profile_path: Optional[str] = None
    gender: Optional[Union[str, int]] = None
    original_name: Optional[str] = None
    credit_id: Optional[str] = None
    also_known_as: Optional[list[str]] = Field(default_factory=list)
    birthday: Optional[str] = None
    deathday: Optional[str] = None
    imdb_id: Optional[str] = None
    known_for_department: Optional[str] = None
    place_of_birth: Optional[str] = None
    popularity: Optional[float] = None
    biography: Optional[str] = None
    # douban
    roles: Optional[list[str]] = Field(default_factory=list)
    title: Optional[str] = None
    url: Optional[str] = None
    avatar: Optional[Union[str, MediaImageSet]] = None
    latin_name: Optional[str] = None
    # bangumi
    career: Optional[list[str]] = Field(default_factory=list)
    relation: Optional[str] = None


def _media_search_result_kind(value: Any) -> str:
    """按稳定字段区分音乐、人物与影视/合集搜索结果。"""
    if isinstance(value, BaseModel):
        value = value.model_dump()
    if isinstance(value, dict):
        if value.get("type") == "音乐" or "music_type" in value:
            return "music"
        if "source" in value and "media_source" not in value:
            return "person"
    return "media"


MediaSearchResult = Annotated[
    Union[
        Annotated[MusicInfo, Tag("music")],
        Annotated[MediaPerson, Tag("person")],
        Annotated[MediaInfo, Tag("media")],
    ],
    Discriminator(_media_search_result_kind),
]


class MediaSearchResults(RootModel[List[MediaSearchResult]]):
    """媒体、音乐、合集与人物的统一搜索结果列表。"""
