from typing import Any, List, Dict, Optional

from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession

from app import schemas
from app.chain.download import DownloadChain
from app.chain.mediaserver import MediaServerChain
from app.core.context import MediaInfo
from app.core.metainfo import MetaInfo
from app.core.security import verify_token
from app.db import get_async_db
from app.db.mediaserver_oper import MediaServerOper
from app.db.models import MediaServerItem
from app.db.systemconfig_oper import SystemConfigOper
from app.helper.mediaserver import MediaServerHelper
from app.schemas import MediaType, NotExistMediaInfo
from app.schemas.types import SystemConfigKey

router = APIRouter()


@router.get("/play/{itemid:path}", summary="在线播放")
def play_item(
    itemid: str, _: schemas.TokenPayload = Depends(verify_token)
) -> schemas.Response:
    """
    获取媒体服务器播放页面地址
    """
    if not itemid:
        return schemas.Response(success=False, message="参数错误")
    configs = MediaServerHelper().get_configs()
    if not configs:
        return schemas.Response(success=False, message="未配置媒体服务器")
    media_chain = MediaServerChain()
    for name in configs.keys():
        item = media_chain.iteminfo(server=name, item_id=itemid)
        if item:
            play_url = media_chain.get_play_url(server=name, item_id=itemid)
            if play_url:
                return schemas.Response(
                    success=True,
                    data={
                        "url": play_url,
                        "item_id": item.item_id or itemid,
                        "server_id": item.server_id,
                        "server_type": item.server,
                    },
                )
    return schemas.Response(success=False, message="未找到播放地址")


@router.get(
    "/exists", summary="查询本地是否存在（数据库）", response_model=schemas.Response
)
async def exists_local(
    title: Optional[str] = None,
    year: Optional[str] = None,
    mtype: Optional[str] = None,
    tmdbid: Optional[int] = None,
    season: Optional[int] = None,
    db: AsyncSession = Depends(get_async_db),
    _: schemas.TokenPayload = Depends(verify_token),
) -> Any:
    """
    判断本地是否存在
    """
    meta = MetaInfo(title)
    if season is None:
        season = meta.begin_season
    # 返回对象
    ret_info = {}
    # 本地数据库是否存在
    exist: MediaServerItem = await MediaServerOper(db).async_exists(
        title=meta.name, year=year, mtype=mtype, tmdbid=tmdbid, season=season
    )
    if exist:
        ret_info = {"id": exist.item_id}
    return schemas.Response(success=True if exist else False, data={"item": ret_info})


@router.post(
    "/exists_remote",
    summary="查询已存在的剧集信息（媒体服务器）",
    response_model=Dict[int, list],
)
def exists(
    media_in: schemas.MediaInfo, _: schemas.TokenPayload = Depends(verify_token)
) -> Any:
    """
    根据媒体信息查询媒体库已存在的剧集信息
    """
    # 转化为媒体信息对象
    mediainfo = MediaInfo()
    mediainfo.from_dict(media_in.model_dump())
    existsinfo: schemas.ExistMediaInfo = MediaServerChain().media_exists(
        mediainfo=mediainfo
    )
    if not existsinfo:
        return {}
    if media_in.season is not None:
        return {media_in.season: existsinfo.seasons.get(media_in.season) or []}
    return existsinfo.seasons


@router.post(
    "/notexists",
    summary="查询媒体库缺失信息（媒体服务器）",
    response_model=List[schemas.NotExistMediaInfo],
)
def not_exists(
    media_in: schemas.MediaInfo, _: schemas.TokenPayload = Depends(verify_token)
) -> Any:
    """
    根据媒体信息查询缺失电影/剧集
    """
    # 媒体信息
    meta = MetaInfo(title=media_in.title)
    mtype = MediaType(media_in.type) if media_in.type else None
    if mtype:
        meta.type = mtype
    if media_in.season is not None:
        meta.begin_season = media_in.season
        meta.type = MediaType.TV
    if media_in.year:
        meta.year = media_in.year
    # 转化为媒体信息对象
    mediainfo = MediaInfo()
    mediainfo.from_dict(media_in.model_dump())
    exist_flag, no_exists = DownloadChain().get_no_exists_info(
        meta=meta, mediainfo=mediainfo
    )
    mediakey = mediainfo.tmdb_id or mediainfo.douban_id
    if mediainfo.type == MediaType.MOVIE:
        # 电影已存在时返回空列表，不存在时返回空对像列表
        return [] if exist_flag else [NotExistMediaInfo()]
    elif no_exists and no_exists.get(mediakey):
        # 电视剧返回缺失的剧集
        return list(no_exists.get(mediakey).values())
    return []


@router.get(
    "/latest", summary="最新入库条目", response_model=List[schemas.MediaServerPlayItem]
)
def latest(
    server: str,
    count: Optional[int] = 20,
    userinfo: schemas.TokenPayload = Depends(verify_token),
) -> Any:
    """
    获取媒体服务器最新入库条目
    """
    return (
        MediaServerChain().latest(
            server=server, count=count, username=userinfo.username
        )
        or []
    )


@router.get(
    "/playing", summary="正在播放条目", response_model=List[schemas.MediaServerPlayItem]
)
def playing(
    server: str,
    count: Optional[int] = 12,
    userinfo: schemas.TokenPayload = Depends(verify_token),
) -> Any:
    """
    获取媒体服务器正在播放条目
    """
    return (
        MediaServerChain().playing(
            server=server, count=count, username=userinfo.username
        )
        or []
    )


@router.get(
    "/library", summary="媒体库列表", response_model=List[schemas.MediaServerLibrary]
)
def library(
    server: str,
    hidden: Optional[bool] = False,
    userinfo: schemas.TokenPayload = Depends(verify_token),
) -> Any:
    """
    获取媒体服务器媒体库列表
    """
    return (
        MediaServerChain().librarys(
            server=server, username=userinfo.username, hidden=hidden
        )
        or []
    )


@router.get("/clients", summary="查询可用媒体服务器", response_model=List[dict])
async def clients(_: schemas.TokenPayload = Depends(verify_token)) -> Any:
    """
    查询可用媒体服务器
    """
    mediaservers: List[dict] = SystemConfigOper().get(SystemConfigKey.MediaServers)
    if mediaservers:
        return [
            {"name": d.get("name"), "type": d.get("type")}
            for d in mediaservers
            if d.get("enabled")
        ]
    return []
