"""
任务API模块

提供任务状态和日志的API接口
"""

from flask import Blueprint, jsonify, request, g
from app.services.auth.decorators import login_required
from .tasks import tasks_status, get_task
from .utils import generation_status, get_generation_status
import os
import json
import datetime

bp_tasks_api = Blueprint('generate_tasks_api', __name__)


def read_log_file(log_file, position=0):
    """读取日志文件的新内容"""
    if not log_file:
        return [], 0
    
    # 如果路径是相对路径，尝试转换为绝对路径
    if not os.path.isabs(log_file):
        from pathlib import Path
        # 尝试从项目根目录解析
        project_root = Path(__file__).parent.parent.parent.parent
        abs_log_file = project_root / log_file
        if abs_log_file.exists():
            log_file = str(abs_log_file)
        else:
            # 如果还是不存在，尝试原始路径
            if not os.path.exists(log_file):
                return [], 0
    elif not os.path.exists(log_file):
        return [], 0
    
    # 优先读取可读格式的日志文件
    readable_log_file = log_file.replace('.txt', '_readable.txt')
    actual_log_file = readable_log_file if os.path.exists(readable_log_file) else log_file
    
    new_logs = []
    new_position = position
    
    try:
        with open(actual_log_file, 'r', encoding='utf-8') as f:
            # 如果 position 为 0，从头开始读取所有内容
            if position == 0:
                content = f.read()
                # 获取文件总大小
                f.seek(0, 2)  # 移动到文件末尾
                new_position = f.tell()
            else:
                f.seek(position)
                content = f.read()
                new_position = f.tell()
            
            if content:
                # 按行分割，保留空行（用于显示格式）
                new_logs = content.split('\n')
                # 如果最后一行是空行，移除它（避免显示多余的空白）
                if new_logs and new_logs[-1] == '':
                    new_logs = new_logs[:-1]
    except Exception as e:
        print(f"读取日志文件失败: {str(e)}", flush=True)
    
    return new_logs, new_position


@bp_tasks_api.route('/api/tasks/<task_id>/log', methods=['GET'])
@login_required
def get_task_log(task_id):
    """直接读取任务日志文件（不轮询）"""
    user_id = g.user.id if hasattr(g, 'user') and g.user else None
    if not user_id:
        return jsonify({"status": "error", "message": "未登录"}), 401
    
    # 获取任务信息
    task = get_task(task_id)
    
    # 如果任务不在内存中，尝试从数据库恢复（针对已完成的任务）
    if not task:
        if task_id.startswith('challenge-'):
            try:
                challenge_id = int(task_id.replace('challenge-', ''))
                from app.models.database.operations import get_challenge_record
                challenge_data = get_challenge_record(challenge_id)
                
                if challenge_data:
                    challenge_user_id = challenge_data.get('user_id')
                    if str(challenge_user_id) != str(user_id):
                        if not (hasattr(g, 'user') and g.user and g.user.role in ['admin', 'moderator']):
                            return jsonify({"status": "error", "message": "无权访问"}), 403
                    
                    task = {
                        'user_id': str(user_id),
                        'challenge_id': challenge_id,
                        'log_file': challenge_data.get('log_file')
                    }
            except Exception as e:
                print(f"从数据库读取题目失败: {str(e)}")
    
    if not task:
        return jsonify({"status": "error", "message": "任务不存在"}), 404
    
    # 检查权限
    if str(task.get('user_id')) != str(user_id):
        if not (hasattr(g, 'user') and g.user and g.user.role in ['admin', 'moderator']):
            return jsonify({"status": "error", "message": "无权访问"}), 403
    
    # 获取日志文件路径
    log_file = task.get('log_file')
    if not log_file:
        # 尝试从 generation_statuses 获取
        task_status = get_generation_status(task_id)
        if task_status:
            log_file = task_status.get('log_file')
    
    # 如果还是没有找到，尝试根据 task_id 或 challenge_id 查找日志文件
    if not log_file:
        # 从 task_id 提取后缀（用于匹配日志文件名）
        task_suffix = task_id.split('-')[-1][:8] if '-' in task_id else task_id[:8]
        from pathlib import Path
        project_root = Path(__file__).parent.parent.parent.parent
        import glob
        
        # 优先查找题目目录下的 logs 子目录（针对已完成的任务）
        challenge_id = task.get('challenge_id')
        output_dir = task.get('output_dir')
        
        if challenge_id and not output_dir:
            # 如果有 challenge_id 但没有 output_dir，尝试从数据库获取
            try:
                from app.models.database.operations import get_challenge_record
                challenge_data = get_challenge_record(challenge_id)
                if challenge_data:
                    output_dir = challenge_data.get('output_dir')
            except Exception as e:
                print(f"从数据库获取 output_dir 失败: {str(e)}")
        
        if output_dir:
            # 在题目目录下的 logs 子目录中查找
            challenge_logs_dir = Path(output_dir) / 'logs'
            if challenge_logs_dir.exists():
                pattern = str(challenge_logs_dir / f"ai_service_{task_suffix}_*.txt")
                matching_files = glob.glob(pattern)
                if matching_files:
                    # 使用最新的文件
                    log_file = max(matching_files, key=lambda p: Path(p).stat().st_mtime)
                    # 更新任务状态中的日志文件路径
                    from .tasks import update_task
                    update_task(task_id, log_file=log_file)
                    # 更新数据库中的日志文件路径
                    if challenge_id:
                        try:
                            from app.models.database.operations import update_challenge
                            update_challenge(challenge_id, {'log_file': log_file})
                        except Exception as e:
                            print(f"更新数据库日志路径失败: {str(e)}")
        
        # 如果还是没有找到，在根 logs 目录中查找（向后兼容）
        if not log_file:
            logs_dir = project_root / 'logs'
            if logs_dir.exists():
                pattern = str(logs_dir / f"ai_service_{task_suffix}_*.txt")
                matching_files = glob.glob(pattern)
                if matching_files:
                    # 使用最新的文件
                    log_file = max(matching_files, key=lambda p: Path(p).stat().st_mtime)
                    # 更新任务状态中的日志文件路径
                    from .tasks import update_task
                    update_task(task_id, log_file=log_file)
    
    if not log_file:
        return jsonify({
            "status": "success",
            "logs": [],
            "log_file": None,
            "log_position": 0
        })
    
    # 获取前端传递的日志位置（如果有）
    request_position = request.args.get('position', type=int)
    if request_position is None:
        # 如果没有传递 position，尝试从任务状态中获取
        task_status = get_generation_status(task_id)
        if task_status:
            request_position = task_status.get('log_position', 0)
        else:
            request_position = 0
    
    # 从指定位置读取新日志（而不是从0开始）
    new_logs, new_position = read_log_file(log_file, request_position)
    
    return jsonify({
        "status": "success",
        "logs": new_logs,
        "log_file": log_file,
        "log_position": new_position
    })


@bp_tasks_api.route('/api/tasks/<task_id>/status', methods=['GET'])
@login_required
def get_task_status(task_id):
    """获取任务状态（不包含日志，日志通过 /log 端点获取）"""
    user_id = g.user.id if hasattr(g, 'user') and g.user else None
    if not user_id:
        return jsonify({"status": "error", "message": "未登录"}), 401
    
    # 获取任务信息
    task = get_task(task_id)
    
    # 如果任务不在内存中，尝试从数据库恢复（针对已完成的任务）
    if not task:
        # 如果是虚拟任务ID（challenge-{id}格式），从数据库读取
        if task_id.startswith('challenge-'):
            try:
                challenge_id = int(task_id.replace('challenge-', ''))
                from app.models.database.operations import get_challenge_record
                challenge_data = get_challenge_record(challenge_id)
                
                if challenge_data:
                    # 检查权限：题目必须属于当前用户（除非是管理员）
                    challenge_user_id = challenge_data.get('user_id')
                    if str(challenge_user_id) != str(user_id):
                        if not (hasattr(g, 'user') and g.user and g.user.role in ['admin', 'moderator']):
                            return jsonify({"status": "error", "message": "无权访问"}), 403
                    
                    # 创建虚拟任务对象
                    challenge_type = challenge_data.get('challenge_type', 'web')
                    category_id = challenge_type if challenge_type else 'web'
                    
                    created_at = challenge_data.get('created_at')
                    if isinstance(created_at, str):
                        try:
                            created_at = datetime.datetime.fromisoformat(created_at.replace('Z', '+00:00'))
                        except:
                            created_at = datetime.datetime.now()
                    elif created_at is None:
                        created_at = datetime.datetime.now()
                    
                    updated_at = challenge_data.get('updated_at', created_at)
                    if isinstance(updated_at, str):
                        try:
                            updated_at = datetime.datetime.fromisoformat(updated_at.replace('Z', '+00:00'))
                        except:
                            updated_at = created_at
                    elif updated_at is None:
                        updated_at = created_at
                    
                    task = {
                        'user_id': str(user_id),
                        'category_id': category_id,
                        'name': challenge_data.get('name', '未命名题目'),
                        'status': 'completed',
                        'created_at': created_at,
                        'updated_at': updated_at,
                        'challenge_id': challenge_id,
                        'output_dir': challenge_data.get('output_dir'),
                        'log_file': challenge_data.get('log_file')
                    }
            except Exception as e:
                print(f"从数据库读取题目失败: {str(e)}")
                import traceback
                traceback.print_exc()
    
    if not task:
        return jsonify({"status": "error", "message": "任务不存在"}), 404
    
    # 检查任务是否属于当前用户（除非是管理员）
    if str(task.get('user_id')) != str(user_id):
        if not (hasattr(g, 'user') and g.user and g.user.role in ['admin', 'moderator']):
            return jsonify({"status": "error", "message": "无权访问"}), 403
    
    # 构建响应（不包含日志，日志通过 /log 端点获取）
    response_data = {
        "status": "success",
        "task": {
            "id": task_id,
            "name": task.get('name', ''),
            "status": task.get('status', 'running'),
            "created_at": task.get('created_at').isoformat() if isinstance(task.get('created_at'), datetime.datetime) else task.get('created_at'),
            "updated_at": task.get('updated_at').isoformat() if isinstance(task.get('updated_at'), datetime.datetime) else task.get('updated_at'),
            "category_id": task.get('category_id', ''),
            "challenge_id": task.get('challenge_id'),
            "error": task.get('error'),
            "log_file": task.get('log_file')  # 返回日志文件路径，前端可以单独请求
        }
    }
    
    # 从 generation_statuses 同步最新状态
    # 对于多任务并发，每个任务都有独立的状态
    task_status = get_generation_status(task_id)
    if task_status and task_status.get('task_id') == task_id:
        # 同步最新状态
        response_data["task"]["message"] = task_status.get('message', task.get('message', ''))
        response_data["task"]["stage_names"] = task_status.get('stage_names', {})
        response_data["task"]["total_stages"] = task_status.get('total_stages', 0)

        # 检查 generation_statuses 中的完成状态
        if task_status.get('completed') and task.get('status') == 'running':
            # generation_statuses 显示已完成，但 tasks_status 还是 running
            # 同步完成状态到 tasks_status
            from .tasks import update_task
            update_task(task_id,
                       status='completed',
                       message=task_status.get('message', '生成完成'),
                       challenge_id=task_status.get('challenge_id'))
            response_data["task"]["status"] = 'completed'
            response_data["task"]["challenge_id"] = task_status.get('challenge_id')
        elif task.get('status') == 'running':
            # 任务仍在运行，同步消息
            from .tasks import update_task
            update_task(task_id,
                       message=task_status.get('message', ''))

    return jsonify(response_data)


@bp_tasks_api.route('/api/tasks', methods=['GET'])
@login_required
def list_tasks():
    """获取当前用户的任务列表"""
    from .tasks import get_user_tasks
    
    user_id = g.user.id if hasattr(g, 'user') and g.user else None
    if not user_id:
        return jsonify({"status": "error", "message": "未登录"}), 401
    
    # 获取用户的任务
    user_tasks = get_user_tasks(str(user_id))
    
    # 验证 challenge_id 是否存在（过滤已删除的题目）
    try:
        from app.models.database.operations import get_challenges_by_user
        db_challenges = get_challenges_by_user(user_id)
        existing_challenge_ids = {challenge.get('id') for challenge in db_challenges if challenge.get('id')}
        
        # 过滤掉那些 challenge_id 在数据库中不存在的任务
        user_tasks = {
            task_id: task 
            for task_id, task in user_tasks.items()
            if not task.get('challenge_id') or task.get('challenge_id') in existing_challenge_ids
        }
        
        # 收集内存中已有 challenge_id 的任务
        existing_task_challenge_ids = {
            task.get('challenge_id') 
            for task in user_tasks.values() 
            if task.get('challenge_id')
        }
        
        # 为每个数据库中的题目创建虚拟任务（如果内存中没有）
        # 这样API返回的任务列表和视图显示的任务列表保持一致
        for challenge in db_challenges:
            challenge_id = challenge.get('id')
            if challenge_id and challenge_id not in existing_task_challenge_ids:
                # 创建虚拟任务ID（使用 challenge_id 作为标识）
                virtual_task_id = f"challenge-{challenge_id}"
                
                # 如果内存中没有对应的任务，创建虚拟任务
                if virtual_task_id not in user_tasks:
                    # 转换 challenge_type 为 category_id
                    challenge_type = challenge.get('challenge_type', 'web')
                    category_id = challenge_type if challenge_type else 'web'
                    
                    # 解析创建时间
                    created_at = challenge.get('created_at')
                    if isinstance(created_at, str):
                        try:
                            created_at = datetime.datetime.fromisoformat(created_at.replace('Z', '+00:00'))
                        except:
                            created_at = datetime.datetime.now()
                    elif created_at is None:
                        created_at = datetime.datetime.now()
                    
                    # 创建虚拟任务
                    user_tasks[virtual_task_id] = {
                        'user_id': str(user_id),
                        'category_id': category_id,
                        'name': challenge.get('name', '未命名题目'),
                        'status': 'completed',
                        'created_at': created_at,
                        'updated_at': challenge.get('updated_at', created_at),
                        'challenge_id': challenge_id,
                        'output_dir': challenge.get('output_dir'),
                        'log_file': challenge.get('log_file')
                    }
    except Exception as e:
        print(f"验证 challenge_id 失败: {str(e)}")
        # 如果验证失败，继续使用原始的任务列表（不过滤）
    
    # 转换为列表格式，并从 generation_statuses 同步最新状态
    tasks_list = []
    for task_id, task in user_tasks.items():
        task = task.copy()  # 创建副本，避免修改原始数据

        # 从 generation_statuses 获取最新状态
        task_status = get_generation_status(task_id)
        if task_status and task_status.get('task_id') == task_id:
            # 同步消息
            task['message'] = task_status.get('message', task.get('message', ''))

            # 检查完成状态
            if task_status.get('completed') and task.get('status') == 'running':
                task['status'] = 'completed'
                task['challenge_id'] = task_status.get('challenge_id')
                # 同步到 tasks_status
                from .tasks import update_task
                update_task(task_id,
                           status='completed',
                           challenge_id=task_status.get('challenge_id'))
            elif task.get('status') == 'running':
                # 同步消息
                from .tasks import update_task
                update_task(task_id,
                           message=task_status.get('message', ''))

        tasks_list.append({
            "id": task_id,
            "name": task.get('name', ''),
            "status": task.get('status', 'running'),
            "created_at": task.get('created_at').isoformat() if isinstance(task.get('created_at'), datetime.datetime) else task.get('created_at'),
            "updated_at": task.get('updated_at').isoformat() if isinstance(task.get('updated_at'), datetime.datetime) else task.get('updated_at'),
            "category_id": task.get('category_id', ''),
            "challenge_id": task.get('challenge_id')
        })
    
    # 按创建时间倒序排列
    tasks_list.sort(key=lambda x: x.get('created_at', ''), reverse=True)
    
    return jsonify({
        "status": "success",
        "tasks": tasks_list
    })

