"""MIME and size checks for prompt uploads."""
from __future__ import annotations

import os

from src.config import get_settings
from src.core.exceptions import ValidationError

_ALLOWED_FILE_MIME_TYPES = {
    "application/csv",
    "application/json",
    "application/ndjson",
    "application/pdf",
    "application/msword",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    "application/vnd.ms-excel",
    "application/x-ndjson",
    "text/csv",
    "text/markdown",
    "text/plain",
    # Source code -- e.g. a design/build export an agent uploads instead of
    # retyping into start_build's attachments (see agent_access/asset_upload.py
    # and agent_facade.py's asset_id-backed text-attachment resolution).
    "text/css",
    "text/html",
    "text/javascript",
    "application/javascript",
    "application/typescript",
    "text/x-typescript",
    "text/yaml",
    "application/x-yaml",
    # A zip of several of the above, extracted server-side into individual
    # assets instead of one upload round trip per file -- see
    # agent_access/asset_upload.py's confirm_upload zip branch.
    "application/zip",
    "application/x-zip-compressed",
}

_ALLOWED_FILE_EXTENSIONS = {
    ".csv",
    ".json",
    ".jsonl",
    ".ndjson",
    ".pdf",
    ".doc",
    ".docx",
    ".md",
    ".txt",
    ".zip",
    ".css",
    ".scss",
    ".less",
    ".html",
    ".htm",
    ".js",
    ".mjs",
    ".cjs",
    ".jsx",
    ".ts",
    ".tsx",
    ".vue",
    ".yaml",
    ".yml",
}


def assert_allowed_mime(mime_type: str, filename: str | None = None) -> None:
    m = (mime_type or "").lower().strip()
    if not m:
        raise ValidationError("Missing content type")
    if m.startswith("image/") or m.startswith("audio/") or m.startswith("video/"):
        return
    if m in _ALLOWED_FILE_MIME_TYPES:
        return
    ext = os.path.splitext(filename or "")[1].lower()
    if m == "application/octet-stream" and ext in _ALLOWED_FILE_EXTENSIONS:
        return
    raise ValidationError(f"Unsupported file type: {mime_type}")


def assert_file_size(byte_size: int) -> None:
    settings = get_settings()
    mx = int(getattr(settings, "prompt_media_max_bytes", 25 * 1024 * 1024))
    if byte_size <= 0:
        raise ValidationError("Empty file")
    if byte_size > mx:
        raise ValidationError(f"File too large (max {mx // (1024 * 1024)} MiB)")


def kind_from_mime(mime_type: str) -> str:
    m = (mime_type or "").lower()
    if m.startswith("image/"):
        return "image"
    if m.startswith("audio/"):
        return "audio"
    return "file"
