# -*- coding: utf-8 -*-
"""
日志管理服务

负责日志文件的分类、移动和管理
"""
import os
import shutil
import logging
from pathlib import Path
from typing import Optional, List
from datetime import datetime

logger = logging.getLogger(__name__)


class LogManager:
    """日志管理器"""
    
    def __init__(self, base_log_dir: str = "logs"):
        """
        初始化日志管理器
        
        Args:
            base_log_dir: 基础日志目录
        """
        self.base_log_dir = Path(base_log_dir)
        self.failed_log_dir = self.base_log_dir / "failed"
        self.failed_log_dir.mkdir(parents=True, exist_ok=True)
    
    def move_log_to_challenge(self, log_file: str, challenge_output_dir: str) -> Optional[str]:
        """
        将日志文件移动到题目目录
        
        Args:
            log_file: 原始日志文件路径
            challenge_output_dir: 题目输出目录
            
        Returns:
            新的日志文件路径，如果移动失败则返回None
        """
        if not log_file or not os.path.exists(log_file):
            logger.warning(f"日志文件不存在: {log_file}")
            return None
        
        try:
            log_path = Path(log_file)
            challenge_dir = Path(challenge_output_dir)
            
            # 创建题目目录下的logs子目录
            challenge_log_dir = challenge_dir / "logs"
            challenge_log_dir.mkdir(parents=True, exist_ok=True)
            
            # 移动日志文件
            new_log_path = challenge_log_dir / log_path.name
            shutil.move(str(log_path), str(new_log_path))
            
            logger.info(f"已移动日志文件到题目目录: {new_log_path}")
            
            # 同时移动相关的日志文件（如_readable.txt等）
            self._move_related_logs(log_path, challenge_log_dir)
            
            return str(new_log_path)
            
        except Exception as e:
            logger.error(f"移动日志文件到题目目录失败: {e}", exc_info=True)
            return None
    
    def move_log_to_failed(self, log_file: str, task_id: Optional[str] = None) -> Optional[str]:
        """
        将日志文件移动到失败日志目录
        
        Args:
            log_file: 原始日志文件路径
            task_id: 任务ID（可选，用于命名）
            
        Returns:
            新的日志文件路径，如果移动失败则返回None
        """
        if not log_file or not os.path.exists(log_file):
            logger.warning(f"日志文件不存在: {log_file}")
            return None
        
        try:
            log_path = Path(log_file)
            
            # 生成新的文件名（包含时间戳和任务ID）
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            if task_id:
                new_name = f"{log_path.stem}_{task_id}_{timestamp}{log_path.suffix}"
            else:
                new_name = f"{log_path.stem}_{timestamp}{log_path.suffix}"
            
            new_log_path = self.failed_log_dir / new_name
            shutil.move(str(log_path), str(new_log_path))
            
            logger.info(f"已移动日志文件到失败目录: {new_log_path}")
            
            # 同时移动相关的日志文件
            self._move_related_logs(log_path, self.failed_log_dir, new_name)
            
            return str(new_log_path)
            
        except Exception as e:
            logger.error(f"移动日志文件到失败目录失败: {e}", exc_info=True)
            return None
    
    def _move_related_logs(self, log_path: Path, target_dir: Path, new_name: Optional[str] = None):
        """
        移动相关的日志文件（如_readable.txt等）
        
        Args:
            log_path: 原始日志文件路径
            target_dir: 目标目录
            new_name: 新文件名（可选，如果不提供则使用原文件名）
        """
        try:
            # 查找相关的日志文件
            log_dir = log_path.parent
            log_stem = log_path.stem
            log_suffix = log_path.suffix
            
            # 常见的相关文件模式
            patterns = [
                f"{log_stem}_readable{log_suffix}",
                f"{log_stem}_readable.txt",
                f"{log_stem}.readable",
            ]
            
            for pattern in patterns:
                related_file = log_dir / pattern
                if related_file.exists() and related_file.is_file():
                    try:
                        if new_name:
                            # 如果提供了新名称，需要相应地修改相关文件名
                            # 例如: augment_20250102_120000.txt -> augment_20250102_120000_task123_20250102_130000.txt
                            # 相关文件: augment_20250102_120000_readable.txt -> augment_20250102_120000_task123_20250102_130000_readable.txt
                            new_stem = Path(new_name).stem
                            new_suffix = Path(new_name).suffix
                            # 提取readable部分
                            if '_readable' in pattern:
                                new_related_name = f"{new_stem}_readable{new_suffix}"
                            elif '.readable' in pattern:
                                new_related_name = f"{new_stem}.readable"
                            else:
                                new_related_name = new_name
                            target_file = target_dir / new_related_name
                        else:
                            target_file = target_dir / pattern
                        
                        shutil.move(str(related_file), str(target_file))
                        logger.debug(f"已移动相关日志文件: {related_file.name} -> {target_file.name}")
                    except Exception as e:
                        logger.warning(f"移动相关日志文件失败 {related_file.name}: {e}")
        
        except Exception as e:
            logger.warning(f"查找相关日志文件时出错: {e}")
    
    def cleanup_old_failed_logs(self, days: int = 30) -> int:
        """
        清理旧的失败日志文件
        
        Args:
            days: 保留天数，默认30天
            
        Returns:
            清理的文件数量
        """
        if not self.failed_log_dir.exists():
            return 0
        
        deleted_count = 0
        cutoff_time = datetime.now().timestamp() - (days * 24 * 3600)
        
        try:
            for log_file in self.failed_log_dir.glob('*'):
                if log_file.is_file():
                    try:
                        if log_file.stat().st_mtime < cutoff_time:
                            log_file.unlink()
                            deleted_count += 1
                            logger.debug(f"已删除旧失败日志: {log_file.name}")
                    except Exception as e:
                        logger.warning(f"删除旧失败日志失败 {log_file.name}: {e}")
        
        except Exception as e:
            logger.error(f"清理旧失败日志时出错: {e}", exc_info=True)
        
        if deleted_count > 0:
            logger.info(f"已清理 {deleted_count} 个旧失败日志文件（超过{days}天）")
        
        return deleted_count
    
    def get_log_files_in_challenge(self, challenge_output_dir: str) -> List[str]:
        """
        获取题目目录下的所有日志文件
        
        Args:
            challenge_output_dir: 题目输出目录
            
        Returns:
            日志文件路径列表
        """
        challenge_dir = Path(challenge_output_dir)
        log_dir = challenge_dir / "logs"
        
        if not log_dir.exists():
            return []
        
        log_files = []
        for log_file in log_dir.glob('*'):
            if log_file.is_file():
                log_files.append(str(log_file))
        
        return sorted(log_files)

