"""腾讯云 COS 对象存储上传。"""
from __future__ import annotations

from pathlib import Path
from urllib.parse import quote

from qcloud_cos import CosConfig, CosS3Client

from app.core.config import settings
from app.core.logger import get_logger
from app.core.response import AppError

logger = get_logger(__name__)

# 上传时按扩展名设置 Content-Type，避免浏览器/客户端无法预览或打开
_CONTENT_TYPES = {
    ".pdf": "application/pdf",
    ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    ".doc": "application/msword",
    ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    ".xlsm": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    ".xls": "application/vnd.ms-excel",
    ".png": "image/png",
    ".jpg": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".txt": "text/plain",
}


def _client() -> CosS3Client:
    if not settings.cos_secret_id or not settings.cos_secret_key or not settings.cos_bucket:
        raise AppError("未配置腾讯云 COS（COS_SECRET_ID/COS_SECRET_KEY/COS_BUCKET）")
    config = CosConfig(
        Region=settings.cos_region,
        SecretId=settings.cos_secret_id,
        SecretKey=settings.cos_secret_key,
    )
    return CosS3Client(config)


def _content_disposition(filename: str) -> str:
    """下载文件名头：ASCII 用 filename=，非 ASCII 用 RFC 5987 filename*=。"""
    ascii_name = filename.encode("ascii", "replace").decode("ascii")
    if ascii_name == filename:
        return f'attachment; filename="{filename}"'
    return f"attachment; filename=\"{ascii_name}\"; filename*=UTF-8''{quote(filename)}"


def upload_file(local_path: str | Path, cos_key: str | None = None) -> str:
    """上传本地文件到 COS，返回公开访问 URL。cos_key 为空时用 '{COS_BASE_DIR}/{文件名}'。"""
    local_path = Path(local_path)
    if not local_path.exists():
        raise AppError(f"待上传文件不存在: {local_path}")
    base = (settings.cos_base_dir or "").strip("/")
    key = cos_key or (f"{base}/{local_path.name}" if base else local_path.name)
    content_type = _CONTENT_TYPES.get(local_path.suffix.lower(), "application/octet-stream")
    content_disposition = _content_disposition(local_path.name)
    logger.info("上传 COS key=%s", key)
    _client().upload_file(
        Bucket=settings.cos_bucket, LocalFilePath=str(local_path), Key=key,
        ACL="public-read", ContentType=content_type, ContentDisposition=content_disposition,
    )
    return f"https://{settings.cos_bucket}.cos.{settings.cos_region}.myqcloud.com/{key}"
