from __future__ import annotations

from pydantic import BaseModel, Field

from ..backends.base import ModeError, TelegramBackend
from ..utils.formatting import err, ok, safe_error


class MediaOptions(BaseModel):
    chat_id: str | int | None = Field(default=None, description="ID of the chat")
    file_path_or_url: str | None = Field(
        default=None, description="Path or URL of the file to send"
    )
    message_id: int | None = Field(
        default=None, description="Message ID for downloading"
    )
    caption: str | None = Field(default=None, description="Caption for the media")
    output_dir: str | None = Field(
        default=None, description="Output directory for download"
    )


_ACTION_TO_MEDIA_TYPE = {
    "send_photo": "photo",
    "send_file": "document",
    "send_voice": "voice",
    "send_video": "video",
}


async def handle_media(
    backend: TelegramBackend,
    action: str,
    options: MediaOptions,
) -> str:
    try:
        if action in _ACTION_TO_MEDIA_TYPE:
            if not options.chat_id or not options.file_path_or_url:
                return err(
                    f"'{action}' requires chat_id and file_path_or_url. "
                    "file_path_or_url: local path or HTTP(S) URL. "
                    "Limits: photo 10MB, file/voice/video 50MB (2GB local in user mode)."
                )
            media_type = _ACTION_TO_MEDIA_TYPE[action]
            result = await backend.send_media(
                options.chat_id,
                media_type,
                options.file_path_or_url,
                caption=options.caption,
            )
            return ok(result)

        if action == "download":
            if not options.chat_id or options.message_id is None:
                return err("'download' requires chat_id and message_id")
            path = await backend.download_media(
                options.chat_id, options.message_id, output_dir=options.output_dir
            )
            return ok({"path": path})

        import difflib

        valid = sorted([*_ACTION_TO_MEDIA_TYPE, "download"])
        closest = difflib.get_close_matches(action, valid, n=1)
        suggestion = f" Did you mean '{closest[0]}'?" if closest else ""
        return err(f"Unknown action '{action}'.{suggestion} Valid: {'|'.join(valid)}")
    except ModeError as e:
        return err(str(e))
    except Exception as e:
        return safe_error(e)
