"""
skills/file_send.py - Agent 文件发送工具
========================================
让 Agent 可以向用户发送文件（图片、PDF、文档等）。

[v1.20.8] 修复:
- 新增 get_public_base_url() 函数，生成文件下载的绝对 URL
- 支持 MYAGENT_PUBLIC_URL 环境变量和 config.json 中 public_url 字段
- 平台消息中的文件链接可正确访问
"""
import os
import json
import uuid
import time
import asyncio
from pathlib import Path
from core.logger import get_logger

logger = get_logger("myagent.skill.file_send")

UPLOADS_DIR = Path(__file__).parent.parent / "data" / "uploads"
UPLOADS_DIR.mkdir(parents=True, exist_ok=True)


def get_public_base_url() -> str:
    """[v1.20.8] 获取公开访问的基础 URL（带协议头）。

    优先级: 环境变量 MYAGENT_PUBLIC_URL > config.json public_url 字段 > 空（仅返回相对路径）
    用法示例: http://your-server.com:8767 或 https://your-domain.com

    结果会被缓存，避免重复读取配置文件。
    """
    # 缓存: 同一进程生命周期内只读取一次配置
    if get_public_base_url._cached is not None:
        return get_public_base_url._cached

    # 1. 环境变量
    env_url = os.environ.get("MYAGENT_PUBLIC_URL", "").strip().rstrip("/")
    if env_url:
        get_public_base_url._cached = env_url
        return env_url

    # 2. config.json
    try:
        from config import ConfigManager
        cm = ConfigManager()
        cfg = cm.config
        public_url = getattr(cfg, "public_url", "").strip().rstrip("/")
        if public_url:
            get_public_base_url._cached = public_url
            return public_url
    except Exception:
        pass

    get_public_base_url._cached = ""
    return ""

get_public_base_url._cached = None  # type: ignore


class FileSendSkill:
    """文件发送技能 — Agent 可通过此技能向用户发送文件"""

    name = "file_send"
    description = "向用户发送文件。支持发送已存在的文件路径，或由代码生成的文件。"
    parameters = {
        "type": "object",
        "properties": {
            "file_path": {
                "type": "string",
                "description": "要发送的文件路径（绝对路径或相对路径）"
            },
            "description": {
                "type": "string",
                "description": "文件描述（可选）"
            }
        },
        "required": ["file_path"]
    }

    async def execute(self, file_path: str, description: str = "", stream_callback=None) -> dict:
        """执行文件发送 — 将文件复制到上传目录，返回 file_id"""
        file_path = file_path.strip().strip("'\"")
        fpath = Path(file_path)
        if not fpath.exists():
            return {"success": False, "error": f"文件不存在: {file_path}"}
        if not fpath.is_file():
            return {"success": False, "error": f"不是文件: {file_path}"}

        try:
            file_id = str(uuid.uuid4())[:12]
            date_dir = UPLOADS_DIR / time.strftime("%Y-%m")
            date_dir.mkdir(parents=True, exist_ok=True)
            stored_name = f"{file_id}_{fpath.name}"
            stored_path = date_dir / stored_name

            import shutil
            shutil.copy2(str(fpath), str(stored_path))

            mime_map = {
                ".pdf": "application/pdf", ".png": "image/png", ".jpg": "image/jpeg",
                ".jpeg": "image/jpeg", ".gif": "image/gif", ".webp": "image/webp",
                ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
                ".txt": "text/plain", ".csv": "text/csv", ".md": "text/markdown",
                ".json": "application/json", ".html": "text/html",
                ".mp3": "audio/mpeg", ".mp4": "video/mp4", ".wav": "audio/wav",
                ".webm": "video/webm", ".ogg": "audio/ogg", ".flac": "audio/flac",
                ".zip": "application/zip", ".tar.gz": "application/gzip",
            }
            mime = mime_map.get(fpath.suffix.lower(), "application/octet-stream")
            size = stored_path.stat().st_size

            base_url = get_public_base_url()
            result = {
                "success": True,
                "file_id": file_id,
                "name": fpath.name,
                "type": mime,
                "size": size,
                "description": description or f"文件: {fpath.name}",
                "url": f"{base_url}/api/file/{file_id}?name={fpath.name}",
                "download_url": f"{base_url}/api/file/{file_id}/download?name={fpath.name}",
            }

            logger.info(f"文件发送成功: {fpath.name} -> {file_id}")
            return result

        except Exception as e:
            logger.error(f"文件发送失败: {e}")
            return {"success": False, "error": str(e)}
