import hashlib
import os
import json
from pathlib import Path
from uuid import uuid4
from typing import Optional
from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Depends
from sqlalchemy.orm import Session
from pydantic import BaseModel
from datetime import datetime

from backend.models.database import get_db, init_db, Material, ProjectTemplate
from backend.services.input_handler import InputHandler
from backend.integrations.dossierai_client import get_dossierai_client

router = APIRouter()

DATA_DIR = Path(__file__).parent.parent.parent / "data" / "raw"
DATA_DIR.mkdir(parents=True, exist_ok=True)


class MaterialResponse(BaseModel):
    id: str
    project_id: Optional[int] = None
    project_name: Optional[str] = None
    file_name: str
    file_type: str
    file_hash: str
    file_size: int
    storage_path: str
    status: str
    issue_type: Optional[str] = None
    issue_id: Optional[str] = None
    raw_content: Optional[str] = None
    rawContent: Optional[str] = None
    processed_content: Optional[str] = None
    processedContent: Optional[str] = None
    template_id: Optional[str] = None
    is_duplicate: bool = False
    created_at: datetime
    createdAt: datetime
    updated_at: datetime
    updatedAt: datetime

    class Config:
        from_attributes = True


class MaterialProcessRequest(BaseModel):
    instruction: Optional[str] = None
    template_id: Optional[str] = None


class MaterialConvertRequest(BaseModel):
    template_id: str


class MaterialListResponse(BaseModel):
    items: list
    total: int
    page: int
    page_size: int


def model_to_dict(material: Material, project_name: str = None) -> dict:
    """将Material模型转换为字典"""
    created_at = material.created_at.isoformat() if material.created_at else ""
    updated_at = material.updated_at.isoformat() if material.updated_at else ""
    raw_content = material.raw_content or ""
    processed_content = material.processed_content or ""
    return {
        "id": material.id,
        "project_id": material.project_id,
        "project_name": project_name,
        "file_name": material.file_name,
        "file_type": material.file_type,
        "file_hash": material.file_hash,
        "file_size": material.file_size,
        "storage_path": material.storage_path,
        "status": material.status,
        "issue_type": material.issue_type,
        "issue_id": material.issue_id,
        "rawContent": raw_content,
        "raw_content": raw_content,
        "processedContent": processed_content,
        "processed_content": processed_content,
        "template_id": material.template_id,
        "route_target": material.route_target,
        "route_history": material.route_history,
        "is_duplicate": False,
        "createdAt": created_at,
        "updatedAt": updated_at,
        "created_at": created_at,
        "updated_at": updated_at,
    }


@router.get("/materials", response_model=MaterialListResponse)
async def list_materials(
    page: int = 1,
    page_size: int = 20,
    project_id: Optional[int] = None,
    db: Session = Depends(get_db)
):
    """获取材料列表"""
    query = db.query(Material)
    
    if project_id:
        query = query.filter(Material.project_id == project_id)
    
    total = query.count()
    items = query.offset((page - 1) * page_size).limit(page_size).all()
    
    result_items = []
    for material in items:
        project = material.project if material.project_id else None
        project_name = project.name if project else None
        result_items.append(model_to_dict(material, project_name))
    
    return {
        "items": result_items,
        "total": total,
        "page": page,
        "page_size": page_size
    }


@router.get("/materials/{material_id}")
async def get_material(material_id: str, db: Session = Depends(get_db)):
    """获取材料详情"""
    material = db.query(Material).filter(Material.id == material_id).first()
    if not material:
        raise HTTPException(status_code=404, detail="Material not found")
    
    project = material.project if material.project_id else None
    project_name = project.name if project else None
    
    return model_to_dict(material, project_name)


@router.post("/materials")
async def upload_material(
    file: UploadFile = File(...),
    project_id: Optional[int] = Form(None),
    db: Session = Depends(get_db)
):
    """上传材料"""
    # 读取文件内容
    content = await file.read()
    file_size = len(content)
    
    # 计算哈希
    file_hash = hashlib.sha256(content).hexdigest()
    
    # 检查重复
    existing = db.query(Material).filter(Material.file_hash == file_hash).first()
    if existing:
        project = existing.project if existing.project_id else None
        project_name = project.name if project else None
        result = model_to_dict(existing, project_name)
        result["is_duplicate"] = True
        return result
    
    # 确定文件类型
    ext = os.path.splitext(file.filename)[1].lower() if file.filename else ''
    file_type = "document"
    if ext in {'.mp3', '.wav', '.m4a', '.ogg', '.flac', '.webm', '.aac', '.aiff', '.wma'}:
        file_type = "audio"
    elif ext in {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.tiff', '.tif'}:
        file_type = "image"
    elif ext in {'.json', '.csv', '.xlsx', '.xls', '.log'}:
        file_type = "data"
    
    # 生成ID和路径
    material_id = str(uuid4())
    project_dir = str(project_id or "unassigned")
    storage_dir = DATA_DIR / project_dir / material_id
    storage_dir.mkdir(parents=True, exist_ok=True)
    storage_path = storage_dir / file.filename
    storage_path.write_bytes(content)
    
    # 路由目标
    route_target = str(storage_dir)
    route_history = f"[{datetime.now().isoformat()}] 初始路由到项目 {project_id or '未指定'}: {route_target}"
    
    # 创建记录
    material = Material(
        id=material_id,
        project_id=project_id,
        file_name=file.filename,
        file_type=file_type,
        file_hash=file_hash,
        file_size=file_size,
        storage_path=str(storage_path),
        status="pending",
        route_target=route_target,
        route_history=route_history
    )
    db.add(material)
    db.commit()
    db.refresh(material)
    
    result = model_to_dict(material)
    result["is_duplicate"] = False
    return result


@router.delete("/materials/{material_id}")
async def delete_material(material_id: str, db: Session = Depends(get_db)):
    """删除材料"""
    material = db.query(Material).filter(Material.id == material_id).first()
    if not material:
        raise HTTPException(status_code=404, detail="Material not found")
    
    # 删除文件
    if material.storage_path and os.path.exists(material.storage_path):
        try:
            os.remove(material.storage_path)
        except Exception:
            pass
    
    db.delete(material)
    db.commit()
    
    return {"success": True}


@router.post("/materials/{material_id}/process")
async def process_material(
    material_id: str,
    request: MaterialProcessRequest,
    db: Session = Depends(get_db)
):
    """处理材料（转写/OCR）"""
    material = db.query(Material).filter(Material.id == material_id).first()
    if not material:
        raise HTTPException(status_code=404, detail="Material not found")
    
    # 更新状态
    material.status = "processing"
    db.commit()
    
    try:
        # 调用InputHandler处理（优先使用SiliconFlow转写）
        input_handler = InputHandler()
        
        result = await input_handler.process(material.storage_path, request.instruction)
        
        # 保存结果
        material.raw_content = result.get("transcript") or result.get("content") or ""
        material.status = "completed"
        db.commit()
        
        project = material.project if material.project_id else None
        project_name = project.name if project else None
        return model_to_dict(material, project_name)
        
    except Exception as e:
        material.status = "failed"
        material.raw_content = f"处理失败: {str(e)}"
        db.commit()
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/materials/{material_id}/convert")
async def convert_material(
    material_id: str,
    request: MaterialConvertRequest,
    db: Session = Depends(get_db)
):
    """模板转换"""
    material = db.query(Material).filter(Material.id == material_id).first()
    if not material:
        raise HTTPException(status_code=404, detail="Material not found")
    
    if not material.raw_content:
        raise HTTPException(status_code=400, detail="请先处理材料")
    
    template = db.query(ProjectTemplate).filter(ProjectTemplate.id == request.template_id).first()
    if not template:
        raise HTTPException(status_code=404, detail="Template not found")
    
    try:
        # 调用LLM转换
        dossierai = get_dossierai_client()
        
        prompt = f"""{template.prompt_template}

请从以下内容中提取信息：
{material.raw_content}

请严格按照上述格式输出。"""
        
        result = await dossierai.chat(message=prompt)
        
        # 保存结果
        material.processed_content = result
        material.template_id = request.template_id
        db.commit()
        
        return result
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/materials/check-duplicate")
async def check_duplicate(
    file: UploadFile = File(...),
    db: Session = Depends(get_db)
):
    """检查重复"""
    content = await file.read()
    file_hash = hashlib.sha256(content).hexdigest()
    
    existing = db.query(Material).filter(Material.file_hash == file_hash).first()
    if existing:
        project = existing.project if existing.project_id else None
        project_name = project.name if project else None
        return {
            "is_duplicate": True,
            "existing_material": model_to_dict(existing, project_name),
            "file_hash": file_hash
        }
    
    return {"is_duplicate": False, "file_hash": file_hash}
