import os
import time
import json
import subprocess
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from logger import get_system_logger, log_exception

# ==========================================
# 接口配置
# ==========================================
SESSION_DIR = r'./session'
CHECK_INTERVAL = 2
OUTPUT_SUBDIR = "split_video"
DONE_FLAG = "split_done.flag"

# 初始化日志
logger = get_system_logger('monitorSongs')
# ==========================================

class SongsJsonHandler(FileSystemEventHandler):
    def on_created(self, event):
        if not event.is_directory and event.src_path.lower().endswith('songs.json'):
            logger.debug(f"检测到歌曲列表创建: {event.src_path}")
            self.process_video_splitting(Path(event.src_path))

    def on_moved(self, event):
        if not event.is_directory and event.dest_path.lower().endswith('songs.json'):
            logger.debug(f"检测到歌曲列表移动: {event.dest_path}")
            self.process_video_splitting(Path(event.dest_path))

    def process_video_splitting(self, json_path):
        work_dir = json_path.parent
        split_dir = work_dir / OUTPUT_SUBDIR
        flag_file = work_dir / DONE_FLAG
        
        # 1. 检查标记位
        if flag_file.exists():
            logger.debug(f"切割已完成，跳过: {work_dir.name}")
            return
        
        logger.info("="*50)
        logger.info(f"检测到新歌曲列表: {work_dir.name}")
        logger.info("="*50)
        
        # 2. 读取并修正 JSON 时间格式
        try:
            with open(json_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
                songs = data.get('songs', [])
            logger.info(f"读取到 {len(songs)} 首歌曲")
        except Exception as e:
            log_exception(logger, e, f"读取 JSON 失败: {json_path}")
            return

        # 3. 定位源视频
        source_video = None
        video_exts = {'.mp4', '.mkv', '.avi', '.mov', '.flv', '.wmv'}
        for f in work_dir.iterdir():
            if f.suffix.lower() in video_exts:
                source_video = f
                break
        
        if not source_video:
            logger.error(f"工作区内未找到源视频文件，跳过")
            return
        
        logger.info(f"源视频: {source_video.name}")
        split_dir.mkdir(parents=True, exist_ok=True)

        # 4. 循环切割
        logger.info(f"开始切割视频片段 (Stream Copy)...")
        
        success_count = 0
        fail_count = 0
        
        for idx, song in enumerate(songs, 1):
            # --- 关键修正：将时间戳中的逗号替换为点号 ---
            raw_start = song.get('start', '00:00:00.000')
            raw_end = song.get('end', '00:00:00.000')
            start = raw_start.replace(',', '.')
            end = raw_end.replace(',', '.')
            
            title = song.get('title', 'UNKNOWN').replace('/', '_').replace('\\', '_')
            artist = song.get('artist', 'UNKNOWN')
            output_filename = f"{idx:02d}_{title}{source_video.suffix}"
            output_path = split_dir / output_filename
            
            if output_path.exists(): 
                logger.info(f"[{idx}] 已存在，跳过: {title}")
                continue

            # 构建高效率切割命令
            # 注意：-ss 在 -i 前面是为了快速定位且避免不必要的解码
            cmd = [
                'ffmpeg', '-y', 
                '-ss', start, 
                '-to', end,
                '-i', str(source_video),
                '-c', 'copy', 
                '-map_metadata', '0',
                str(output_path)
            ]

            try:
                # 使用 subprocess.run 配合 capture_output 捕获详细错误
                res = subprocess.run(cmd, capture_output=True, check=True)
                logger.info(f"[{idx}] ✓ {title} - {artist}")
                success_count += 1
            except subprocess.CalledProcessError as e:
                logger.error(f"[{idx}] ✗ {title} 切割失败")
                logger.error(f"FFmpeg 错误: {e.stderr.decode('utf-8', errors='ignore')[:200]}")
                fail_count += 1

        # 5. 生成完成标记
        flag_file.touch()
        logger.info("="*50)
        logger.info(f"切割任务完成: 成功 {success_count} / 失败 {fail_count}")
        logger.info(f"输出目录: {split_dir}")
        logger.info("="*50)

def main():
    path = Path(SESSION_DIR)
    path.mkdir(parents=True, exist_ok=True)

    logger.info("="*50)
    logger.info("视频切割模块启动")
    logger.info("="*50)
    logger.info(f"监控目录: {SESSION_DIR}")

    event_handler = SongsJsonHandler()
    observer = Observer()
    observer.schedule(event_handler, str(path), recursive=True)
    
    # 启动扫描已存在的 songs.json
    logger.info("扫描现有歌曲列表...")
    scan_count = 0
    for sub_dir in path.iterdir():
        if sub_dir.is_dir():
            json_file = sub_dir / "songs.json"
            if json_file.exists():
                logger.info(f"发现已存在的歌曲列表: {sub_dir.name}")
                event_handler.process_video_splitting(json_file)
                scan_count += 1
    logger.info(f"扫描完成，处理 {scan_count} 个歌曲列表")

    observer.start()
    logger.info("文件监控已启动")
    
    try:
        while True:
            time.sleep(CHECK_INTERVAL)
    except KeyboardInterrupt:
        logger.info("接收到停止信号，正在关闭...")
        observer.stop()
    observer.join()
    logger.info("视频切割模块已停止")

if __name__ == "__main__":
    main()