import os
import time
import shutil
import tempfile
import subprocess
from flask import Blueprint, request, jsonify, current_app
from flask_login import login_required, current_user

# 创建蓝图
draft_bp = Blueprint('draft', __name__)

# 辅助函数：获取模型和数据库实例，避免循环导入
def get_models():
    from src.clients import db
    from src.models import DraftRecording, DraftSegment, Recording
    return db, DraftRecording, DraftSegment, Recording

@draft_bp.route('/create', methods=['POST'])
@login_required
def create_draft():
    """创建新的草稿录音"""
    db, DraftRecording, _, _ = get_models()
    try:
        data = request.json or {}
        draft = DraftRecording(
            user_id=current_user.id,
            name=data.get('name', '未命名录音'),
            recording_mode=data.get('recording_mode', 'microphone'),
            notes=data.get('notes', '')
        )
        db.session.add(draft)
        db.session.commit()
        
        current_app.logger.info(f"已创建草稿录音 {draft.id}，用户 ID：{current_user.id}")
        return jsonify({'success': True, 'draft': draft.to_dict()}), 201
    except Exception as e:
        current_app.logger.error(f"创建草稿失败：{e}")
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@draft_bp.route('/<int:draft_id>/segment', methods=['POST'])
@login_required
def upload_draft_segment(draft_id):
    """上传音频片段到草稿"""
    db, DraftRecording, DraftSegment, _ = get_models()
    try:
        draft = DraftRecording.query.filter_by(id=draft_id, user_id=current_user.id).first()
        if not draft:
            return jsonify({'error': 'Draft not found'}), 404
        
        if 'audio' not in request.files:
            return jsonify({'error': 'No audio file provided'}), 400
        
        audio_file = request.files['audio']
        duration = float(request.form.get('duration', 0))
        transcription = request.form.get('transcription', '')
        
        # 确定片段顺序
        existing_segments = DraftSegment.query.filter_by(draft_id=draft_id).count()
        next_order = existing_segments + 1
        
        # 保存音频文件
        draft_folder = os.path.join(current_app.config.get('UPLOAD_FOLDER', 'data/recordings'), 'drafts', str(current_user.id))
        os.makedirs(draft_folder, exist_ok=True)
        
        filename = f"draft_{draft_id}_segment_{next_order}_{int(time.time())}.webm"
        file_path = os.path.join(draft_folder, filename)
        audio_file.save(file_path)
        
        # 创建片段记录
        segment = DraftSegment(
            draft_id=draft_id,
            order=next_order,
            file_path=file_path,
            duration=duration,
            transcription=transcription
        )
        db.session.add(segment)
        
        # 更新草稿总时长和完整转录文本
        draft.total_duration += duration
        # 如果前端带入的是完整文本，直接保存
        if transcription:
            draft.combined_transcription = transcription
            
        db.session.commit()
        
        current_app.logger.info(f"已上传片段 {segment.id} 到草稿 {draft_id}")
        return jsonify({'success': True, 'segment': segment.to_dict(), 'draft': draft.to_dict()}), 201
    except Exception as e:
        current_app.logger.error(f"上传草稿片段失败：{e}")
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@draft_bp.route('/<int:draft_id>/finalize', methods=['POST'])
@login_required
def finalize_draft(draft_id):
    db, DraftRecording, DraftSegment, _ = get_models()
    try:
        draft = DraftRecording.query.filter_by(id=draft_id, user_id=current_user.id).first()
        if not draft:
            return jsonify({'error': 'Draft not found'}), 404

        segments = DraftSegment.query.filter_by(draft_id=draft_id).order_by(DraftSegment.order).all()
        if not segments:
            return jsonify({'error': 'No segments to merge'}), 400

        data = request.get_json(silent=True) or request.form or {}
        notes = data.get('notes') or draft.notes
        language = data.get('language', '')

        def _optional_int(value):
            try:
                return int(value) if value not in (None, '') else None
            except (TypeError, ValueError):
                return None

        min_speakers = _optional_int(data.get('min_speakers'))
        max_speakers = _optional_int(data.get('max_speakers'))

        tag_ids = data.get('tag_ids') or []
        if isinstance(tag_ids, str):
            tag_ids = [item for item in tag_ids.split(',') if item]
        selected_tags = []
        if tag_ids:
            from src.models import Tag
            selected_tags = Tag.query.filter(
                Tag.user_id == current_user.id,
                Tag.id.in_(tag_ids)
            ).all()

        upload_folder = current_app.config.get('UPLOAD_FOLDER', 'data/recordings')
        os.makedirs(upload_folder, exist_ok=True)
        output_filename = f"draft_{draft_id}_{int(time.time())}.webm"
        output_path = os.path.join(upload_folder, output_filename)

        if len(segments) == 1:
            shutil.copy(segments[0].file_path, output_path)
        else:
            with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as list_file:
                for seg in segments:
                    abs_path = os.path.abspath(seg.file_path).replace("'", "'\\''")
                    list_file.write(f"file '{abs_path}'\n")
                list_file_path = list_file.name

            try:
                cmd = ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', list_file_path, '-c', 'copy', output_path]
                result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
                if result.returncode != 0:
                    current_app.logger.error(f"草稿 FFmpeg 合并失败：{result.stderr}")
                    return jsonify({'error': f'FFmpeg 合并失败：{result.stderr}'}), 500
            finally:
                if os.path.exists(list_file_path):
                    os.remove(list_file_path)

        from src.api.recording import create_recording_from_existing_file
        recording = create_recording_from_existing_file(
            filepath=output_path,
            original_filename=output_filename,
            notes=notes,
            selected_tags=selected_tags,
            language=language,
            min_speakers=min_speakers,
            max_speakers=max_speakers,
            mime_type='audio/webm',
            processing_source='draft'
        )

        for seg in segments:
            if os.path.exists(seg.file_path):
                try:
                    os.remove(seg.file_path)
                except Exception as e:
                    current_app.logger.warning(f"删除草稿片段文件失败：{seg.file_path}，错误：{e}")

        db.session.delete(draft)
        db.session.commit()

        current_app.logger.info(f"草稿 {draft_id} 已定稿为录音 {recording.id}")
        return jsonify({'success': True, 'recording': recording.to_dict()}), 202
    except Exception as e:
        current_app.logger.error(f"草稿定稿失败：{e}")
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@draft_bp.route('/list', methods=['GET'])
@login_required
def list_drafts():
    """获取当前用户的所有草稿"""
    db, DraftRecording, _, _ = get_models()
    try:
        drafts = DraftRecording.query.filter_by(user_id=current_user.id).order_by(DraftRecording.updated_at.desc()).all()
        return jsonify([draft.to_dict() for draft in drafts])
    except Exception as e:
        current_app.logger.error(f"获取草稿列表失败：{e}")
        return jsonify({'error': str(e)}), 500

@draft_bp.route('/<int:draft_id>', methods=['GET'])
@login_required
def get_draft(draft_id):
    """获取单个草稿详情"""
    db, DraftRecording, DraftSegment, _ = get_models()
    try:
        draft = DraftRecording.query.filter_by(id=draft_id, user_id=current_user.id).first()
        if not draft:
            return jsonify({'error': 'Draft not found'}), 404
        
        # 获取片段列表
        segments = DraftSegment.query.filter_by(draft_id=draft_id).order_by(DraftSegment.order).all()
        
        result = draft.to_dict()
        result['segments'] = [seg.to_dict() for seg in segments]
        
        # 合并返回所有片段的转录文本
        if draft.combined_transcription:
            result['combined_transcription'] = draft.combined_transcription
        else:
            result['combined_transcription'] = '\n'.join([seg.transcription or '' for seg in segments if seg.transcription])
        
        return jsonify(result)
    except Exception as e:
        current_app.logger.error(f"获取草稿详情失败：{e}")
        return jsonify({'error': str(e)}), 500

@draft_bp.route('/<int:draft_id>', methods=['DELETE'])
@login_required
def delete_draft(draft_id):
    """删除草稿及其所有片段"""
    db, DraftRecording, DraftSegment, _ = get_models()
    try:
        draft = DraftRecording.query.filter_by(id=draft_id, user_id=current_user.id).first()
        if not draft:
            return jsonify({'error': 'Draft not found'}), 404
        
        # 删除片段文件
        segments = DraftSegment.query.filter_by(draft_id=draft_id).all()
        for seg in segments:
            if os.path.exists(seg.file_path):
                try:
                    os.remove(seg.file_path)
                except Exception as e:
                    current_app.logger.warning(f"删除草稿片段文件失败：{seg.file_path}，错误：{e}")
        
        # 删除草稿记录（片段会级联删除）
        db.session.delete(draft)
        db.session.commit()
        
        current_app.logger.info(f"已删除草稿 {draft_id}")
        return jsonify({'success': True})
    except Exception as e:
        current_app.logger.error(f"删除草稿失败：{e}")
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@draft_bp.route('/<int:draft_id>/rename', methods=['PUT'])
@login_required
def rename_draft(draft_id):
    """重命名草稿"""
    db, DraftRecording, _, _ = get_models()
    try:
        draft = DraftRecording.query.filter_by(id=draft_id, user_id=current_user.id).first()
        if not draft:
            return jsonify({'error': 'Draft not found'}), 404
        
        data = request.json or {}
        new_name = data.get('name')
        if not new_name:
            return jsonify({'error': 'Name is required'}), 400
        
        draft.name = new_name
        db.session.commit()
        
        return jsonify({'success': True, 'draft': draft.to_dict()})
    except Exception as e:
        current_app.logger.error(f"重命名草稿失败：{e}")
        db.session.rollback()
        return jsonify({'error': str(e)}), 500

@draft_bp.route('/<int:draft_id>/notes', methods=['PUT'])
@login_required
def update_draft_notes(draft_id):
    """更新草稿笔记"""
    db, DraftRecording, _, _ = get_models()
    try:
        draft = DraftRecording.query.filter_by(id=draft_id, user_id=current_user.id).first()
        if not draft:
            return jsonify({'error': 'Draft not found'}), 404
        
        data = request.json or {}
        draft.notes = data.get('notes', '')
        db.session.commit()
        
        return jsonify({'success': True, 'draft': draft.to_dict()})
    except Exception as e:
        current_app.logger.error(f"更新草稿笔记失败：{e}")
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@draft_bp.route('/<int:draft_id>/download', methods=['GET'])
@login_required
def download_draft_audio(draft_id):
    """下载草稿的合并音频（用于预览）"""
    db, DraftRecording, DraftSegment, _ = get_models()
    try:
        draft = DraftRecording.query.filter_by(id=draft_id, user_id=current_user.id).first()
        if not draft:
            return jsonify({'error': 'Draft not found'}), 404
        
        segments = DraftSegment.query.filter_by(draft_id=draft_id).order_by(DraftSegment.order).all()
        if not segments:
            return jsonify({'error': 'No segments to download'}), 400
        
        # 如果只有一个片段，直接返回
        if len(segments) == 1:
            from flask import send_file
            return send_file(
                segments[0].file_path,
                as_attachment=False,
                download_name=f"录音草稿_{draft_id}.webm",
                mimetype='audio/webm'
            )
        
        # 多个片段需要合并
        upload_folder = current_app.config.get('UPLOAD_FOLDER', 'data/recordings')
        temp_output = os.path.join(upload_folder, 'drafts', str(current_user.id), f"temp_merged_{draft_id}_{int(time.time())}.webm")
        os.makedirs(os.path.dirname(temp_output), exist_ok=True)
        
        # 创建 FFmpeg 输入列表文件
        with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as list_file:
            for seg in segments:
                abs_path = os.path.abspath(seg.file_path).replace("'", "'\\''")
                list_file.write(f"file '{abs_path}'\n")
            list_file_path = list_file.name
        
        try:
            # 使用 concat demuxer 无损合并
            cmd = ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', list_file_path, '-c', 'copy', temp_output]
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
            
            if result.returncode != 0:
                current_app.logger.error(f"FFmpeg 合并失败：{result.stderr}")
                return jsonify({'error': f'FFmpeg merge failed: {result.stderr}'}), 500
            
            from flask import send_file
            
            # 发送文件后删除临时文件
            response = send_file(
                temp_output,
                as_attachment=False,
                download_name=f"录音草稿_{draft_id}.webm",
                mimetype='audio/webm'
            )
            
            # 由于 send_file 会在发送后关闭文件，我们使用 after_this_request 来清理
            from flask import after_this_request
            @after_this_request
            def cleanup(response):
                try:
                    if os.path.exists(temp_output):
                        os.remove(temp_output)
                except Exception as e:
                    current_app.logger.warning(f"清理临时合并文件失败：{temp_output}，错误：{e}")
                return response
            
            return response
            
        finally:
            # 清理列表文件
            if os.path.exists(list_file_path):
                os.remove(list_file_path)
                
    except Exception as e:
        current_app.logger.error(f"下载草稿音频失败：{e}")
        return jsonify({'error': str(e)}), 500
