from fastapi import APIRouter, HTTPException, BackgroundTasks
from pydantic import BaseModel
from typing import Optional
from pathlib import Path
import uuid
import traceback
import time
from app.services.tts_service import TTSService
from app.services.video_service import VideoService
from app.services.lipsync_service import LipSyncService
from app.core.config import settings

router = APIRouter()

class GenerateRequest(BaseModel):
    text: str
    voice: str = "zh-CN-YunxiNeural"
    material_path: str

tasks = {} # In-memory task store

# 缓存 LipSync 服务实例和健康状态
_lipsync_service: Optional[LipSyncService] = None
_lipsync_ready: Optional[bool] = None
_lipsync_last_check: float = 0

def _get_lipsync_service() -> LipSyncService:
    """获取或创建 LipSync 服务实例（单例模式，避免重复初始化）"""
    global _lipsync_service
    if _lipsync_service is None:
        _lipsync_service = LipSyncService()
    return _lipsync_service

async def _check_lipsync_ready(force: bool = False) -> bool:
    """检查 LipSync 是否就绪（带缓存，5分钟内不重复检查）"""
    global _lipsync_ready, _lipsync_last_check
    
    now = time.time()
    # 5分钟缓存
    if not force and _lipsync_ready is not None and (now - _lipsync_last_check) < 300:
        return _lipsync_ready
    
    lipsync = _get_lipsync_service()
    health = await lipsync.check_health()
    _lipsync_ready = health.get("ready", False)
    _lipsync_last_check = now
    print(f"[LipSync] Health check: ready={_lipsync_ready}")
    return _lipsync_ready

async def _process_video_generation(task_id: str, req: GenerateRequest):
    try:
        start_time = time.time()
        
        # Resolve path if it's relative
        input_material_path = Path(req.material_path)
        if not input_material_path.is_absolute():
            input_material_path = settings.BASE_DIR.parent / req.material_path
            
        tasks[task_id]["status"] = "processing"
        tasks[task_id]["progress"] = 5
        tasks[task_id]["message"] = "正在初始化..."
        
        # 1. TTS - 进度 5% -> 25%
        tasks[task_id]["message"] = "正在生成语音 (TTS)..."
        tasks[task_id]["progress"] = 10
        
        tts = TTSService()
        audio_path = settings.OUTPUT_DIR / f"{task_id}_audio.mp3"
        await tts.generate_audio(req.text, req.voice, str(audio_path))
        
        tts_time = time.time() - start_time
        print(f"[Pipeline] TTS completed in {tts_time:.1f}s")
        tasks[task_id]["progress"] = 25
        
        # 2. LipSync - 进度 25% -> 85%
        tasks[task_id]["message"] = "正在合成唇形 (LatentSync)..."
        tasks[task_id]["progress"] = 30
        
        lipsync = _get_lipsync_service()
        lipsync_video_path = settings.OUTPUT_DIR / f"{task_id}_lipsync.mp4"
        
        # 使用缓存的健康检查结果
        lipsync_start = time.time()
        is_ready = await _check_lipsync_ready()
        
        if is_ready:
            print(f"[LipSync] Starting LatentSync inference...")
            tasks[task_id]["progress"] = 35
            tasks[task_id]["message"] = "正在运行 LatentSync 推理..."
            await lipsync.generate(str(input_material_path), str(audio_path), str(lipsync_video_path))
        else:
            # Skip lipsync if not available
            print(f"[LipSync] LatentSync not ready, copying original video")
            tasks[task_id]["message"] = "唇形同步不可用，使用原始视频..."
            import shutil
            shutil.copy(str(input_material_path), lipsync_video_path)

        lipsync_time = time.time() - lipsync_start
        print(f"[Pipeline] LipSync completed in {lipsync_time:.1f}s")
        tasks[task_id]["progress"] = 85
        
        # 3. Composition - 进度 85% -> 100%
        tasks[task_id]["message"] = "正在合成最终视频..."
        tasks[task_id]["progress"] = 90
        
        video = VideoService()
        final_output = settings.OUTPUT_DIR / f"{task_id}_output.mp4"
        await video.compose(str(lipsync_video_path), str(audio_path), str(final_output))
        
        total_time = time.time() - start_time
        print(f"[Pipeline] Total generation time: {total_time:.1f}s")
        
        tasks[task_id]["status"] = "completed"
        tasks[task_id]["progress"] = 100
        tasks[task_id]["message"] = f"生成完成！耗时 {total_time:.0f} 秒"
        tasks[task_id]["output"] = str(final_output)
        tasks[task_id]["download_url"] = f"/outputs/{final_output.name}"
        
    except Exception as e:
        tasks[task_id]["status"] = "failed"
        tasks[task_id]["message"] = f"错误: {str(e)}"
        tasks[task_id]["error"] = traceback.format_exc()

@router.post("/generate")
async def generate_video(req: GenerateRequest, background_tasks: BackgroundTasks):
    task_id = str(uuid.uuid4())
    tasks[task_id] = {"status": "pending", "task_id": task_id, "progress": 0}
    background_tasks.add_task(_process_video_generation, task_id, req)
    return {"task_id": task_id}

@router.get("/tasks/{task_id}")
async def get_task(task_id: str):
    return tasks.get(task_id, {"status": "not_found"})

@router.get("/tasks")
async def list_tasks():
    return {"tasks": list(tasks.values())}

@router.get("/lipsync/health")
async def lipsync_health():
    """获取 LipSync 服务健康状态"""
    lipsync = _get_lipsync_service()
    return await lipsync.check_health()


@router.get("/generated")
async def list_generated_videos():
    """从文件系统读取生成的视频列表（持久化）"""
    output_dir = settings.OUTPUT_DIR
    videos = []
    
    if output_dir.exists():
        for f in output_dir.glob("*_output.mp4"):
            try:
                stat = f.stat()
                videos.append({
                    "id": f.stem,
                    "name": f.name,
                    "path": f"/outputs/{f.name}",
                    "size_mb": stat.st_size / (1024 * 1024),
                    "created_at": stat.st_ctime
                })
            except Exception:
                continue
    
    # Sort by creation time desc (newest first)
    videos.sort(key=lambda x: x.get("created_at", 0), reverse=True)
    return {"videos": videos}


@router.delete("/generated/{video_id}")
async def delete_generated_video(video_id: str):
    """删除生成的视频"""
    output_dir = settings.OUTPUT_DIR
    
    # 查找匹配的文件
    found = None
    for f in output_dir.glob("*.mp4"):
        if f.stem == video_id:
            found = f
            break
    
    if not found:
        raise HTTPException(404, "Video not found")
    
    try:
        found.unlink()
        # 同时删除相关的临时文件（如果存在）
        task_id = video_id.replace("_output", "")
        for suffix in ["_audio.mp3", "_lipsync.mp4"]:
            temp_file = output_dir / f"{task_id}{suffix}"
            if temp_file.exists():
                temp_file.unlink()
        
        return {"success": True, "message": "视频已删除"}
    except Exception as e:
        raise HTTPException(500, f"删除失败: {str(e)}")

