# -*- coding: utf-8 -*-
# filename: file_preview_types.py
# @Time    : 2025-01-20
# @Author  : Claude Code
# @Email   : noreply@anthropic.com
# @Software: PyCharm
"""Pydantic type definitions for file preview tool"""
from datetime import datetime
from enum import Enum
from typing import Any

from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator


class FilePreviewOptions(BaseModel):
    """预览选项配置

    所有数值字段都会在初始化时自动验证，不符合规则会抛出 ValidationError
    """

    max_file_size: int = Field(
        default=100 * 1024 * 1024, gt=0, description="最大文件大小（字节），必须为正数"
    )
    max_download_size: int = Field(
        default=50 * 1024 * 1024,
        gt=0,
        description="URL 下载最大大小（字节），必须为正数且不超过 max_file_size",
    )
    download_timeout: int = Field(default=30, gt=0, description="下载超时时间（秒），必须为正数")
    max_pages: int = Field(
        default=3, gt=0, le=50, description="PDF 最大预览页数，必须为正数且不超过 50"
    )
    max_chars: int = Field(
        default=1000, gt=0, le=10000, description="文本预览最大字符数，必须为正数且不超过 10000"
    )
    max_preview_slides: int = Field(
        default=3, gt=0, le=100, description="PPT 最大预览页数，必须为正数不超过 100"
    )
    enable_cache: bool = Field(default=True, description="是否启用缓存")
    max_workers: int | None = Field(
        default=None,
        description="并发数，None 表示自动，如果设置必须为正数",
    )

    @field_validator("max_workers")
    @classmethod
    def validate_max_workers(cls, v: int | None) -> int | None:
        """验证并发数"""
        if v is not None and v <= 0:
            raise ValueError(f"max_workers must be positive or None, got {v}")
        return v

    @model_validator(mode="after")
    def validate_relationships(self) -> "FilePreviewOptions":
        """验证跨字段约束"""
        if self.max_download_size > self.max_file_size:
            raise ValueError(
                f"max_download_size ({self.max_download_size}) cannot exceed "
                f"max_file_size ({self.max_file_size})"
            )
        return self


class FilePreviewParams(BaseModel):
    """文件预览工具参数"""

    file_paths: list[str]  # 支持本地路径和 URL
    options: FilePreviewOptions | None = None

    model_config = ConfigDict(extra="ignore")


class FileMetadata(BaseModel):
    """基础元数据（所有格式）"""

    filename: str
    file_size: int  # 字节数
    file_type: str  # MIME type
    created_at: str | None = None  # ISO 格式
    modified_at: str | None = None


class ImageMetadata(BaseModel):
    """图片元数据"""

    width: int
    height: int
    format: str
    mode: str  # RGB, RGBA 等


class PDFMetadata(BaseModel):
    """PDF 元数据"""

    page_count: int
    preview_text: str  # 前 N 页文本


class DocumentMetadata(BaseModel):
    """文档元数据（Word/MD/TXT）"""

    char_count: int
    preview_text: str


class SheetInfo(BaseModel):
    """Sheet 信息"""

    columns: list[str]
    shape: tuple[int, int]  # (rows, cols)
    dtypes: dict[str, str] | None = None  # 列名 -> 数据类型（可选）
    sample_rows: list[dict[str, Any]]  # 前 5 行（智能采样，跳过空行）


class ExcelMetadata(BaseModel):
    """Excel 元数据"""

    sheet_names: list[str]  # 所有 sheet 名称
    sheets: dict[str, SheetInfo]  # sheet_name -> 元数据（仅包含有内容的 sheet）


class SlideInfo(BaseModel):
    """单页幻灯片信息"""

    slide_number: int  # 页码（从 1 开始）
    image: str | None = None  # 截图（base64 或临时文件路径）
    text_content: str  # 文本内容


class PPTMetadata(BaseModel):
    """PPT 元数据"""

    slide_count: int
    preview_slides: list[SlideInfo]  # 前 N 页的每页独立信息


class FilePreviewStatus(Enum):
    """处理状态"""

    SUCCESS = "success"
    FAILED = "failed"
    SKIPPED = "skipped"
    PARTIAL = "partial"


class ErrorCode(Enum):
    """错误码枚举"""

    UNSUPPORTED_FORMAT = "unsupported_format"
    FILE_NOT_FOUND = "file_not_found"
    FILE_TOO_LARGE = "file_too_large"
    DOWNLOAD_FAILED = "download_failed"
    PARSE_ERROR = "parse_error"
    LLM_ERROR = "llm_error"
    CORRUPTED_FILE = "corrupted_file"


class SingleFileResult(BaseModel):
    """单个文件的处理结果"""

    file_path: str
    status: FilePreviewStatus
    error_code: ErrorCode | None = None
    error_message: str | None = None
    metadata: FileMetadata
    format_metadata: dict  # 通用字典，包含特定格式的元数据
    content_summary: str | None = None  # LLM 生成的内容描述
    model: str | None = None  # 使用的 LLM 模型
    token_usage: dict | None = None


class FilePreviewResult(BaseModel):
    """批量处理结果"""

    results: list[SingleFileResult]
    total_files: int
    success_count: int
    failed_count: int
    processed_at: str
