from flask import Flask, render_template, request, jsonify
import subprocess
import os
import uuid
import json

app = Flask(__name__)

CACHE_DIR = "cache"
MAX_CACHE_FILES = 10
METADATA_FILE = os.path.join(CACHE_DIR, 'metadata.json')

voices = {
    "晓晓（温暖女声）": "zh-CN-XiaoxiaoNeural",
    "晓伊（活泼女声）": "zh-CN-XiaoyiNeural",
    "云健（激情男声）": "zh-CN-YunjianNeural",
    "云希（阳光男声）": "zh-CN-YunxiNeural",
    "云夏（可爱男声）": "zh-CN-YunxiaNeural",
    "云扬（新闻男声）": "zh-CN-YunyangNeural",

    "辽宁-小贝（方言）": "zh-CN-liaoning-XiaobeiNeural",
    "陕西-小妮（方言）": "zh-CN-shaanxi-XiaoniNeural",

    "香港-晓佳": "zh-HK-HiuGaaiNeural",
    "香港-晓曼": "zh-HK-HiuMaanNeural",
    "香港-云龙": "zh-HK-WanLungNeural",

    "台湾-晓陈": "zh-TW-HsiaoChenNeural",
    "台湾-晓雨": "zh-TW-HsiaoYuNeural",
    "台湾-云哲": "zh-TW-YunJheNeural"
}

current_process = None


def get_metadata():
    if not os.path.exists(METADATA_FILE):
        return {}
    with open(METADATA_FILE, 'r', encoding='utf-8') as f:
        return json.load(f)


def save_metadata(metadata):
    with open(METADATA_FILE, 'w', encoding='utf-8') as f:
        json.dump(metadata, f, ensure_ascii=False, indent=2)


def clean_cache():
    if not os.path.exists(CACHE_DIR):
        os.makedirs(CACHE_DIR)
        return
    
    files = []
    metadata = get_metadata()
    for f in os.listdir(CACHE_DIR):
        filepath = os.path.join(CACHE_DIR, f)
        if os.path.isfile(filepath) and f.endswith('.mp3'):
            files.append({
                'filepath': filepath,
                'filename': f,
                'created_at': os.path.getctime(filepath),
                'is_favorite': metadata.get(f, {}).get('is_favorite', False)
            })
    
    total_files = len(files)
    if total_files >= MAX_CACHE_FILES:
        files.sort(key=lambda x: x['created_at'])
        
        files_to_delete = []
        non_fav_files = [f for f in files if not f['is_favorite']]
        
        num_files_to_delete = total_files - MAX_CACHE_FILES + 1
        
        if len(non_fav_files) >= num_files_to_delete:
            files_to_delete = non_fav_files[:num_files_to_delete]
        elif len(non_fav_files) > 0:
            files_to_delete = non_fav_files
        
        for file_info in files_to_delete:
            filename = file_info['filename']
            if filename in metadata:
                del metadata[filename]
            os.remove(file_info['filepath'])
        
        if files_to_delete:
            save_metadata(metadata)


@app.route('/')
def index():
    return render_template('index.html', voices=voices)


@app.route('/speak', methods=['POST'])
def speak():
    global current_process

    text = request.form.get('text')
    voice = request.form.get('voice')
    loop = request.form.get('loop') == 'true'
    interval = int(request.form.get('interval', 5))

    if not text:
        return jsonify({'status': 'error', 'message': '请输入广播内容'})

    clean_cache()

    filename = f"{uuid.uuid4()}.mp3"
    filepath = os.path.join(CACHE_DIR, filename)

    voice_name = voices.get(voice, 'zh-CN-YunxiNeural')

    subprocess.run([
        'python3',
        '-m',
        'edge_tts',
        '--voice',
        voice_name,
        '--text',
        text,
        '--write-media',
        filepath
    ])

    metadata = get_metadata()
    display_name = text[:30] + '...' if len(text) > 30 else text
    metadata[filename] = {
        'display_name': display_name,
        'text': text,
        'voice': voice,
        'is_favorite': False
    }
    save_metadata(metadata)

    if current_process:
        current_process.kill()

    subprocess.run(['pkill', '-9', 'mpg123'])

    if loop:
        current_process = subprocess.Popen([
            'bash',
            'player.sh',
            filepath,
            str(interval)
        ])
    else:
        current_process = subprocess.Popen([
            'mpg123',
            '-o',
            'alsa',
            '-a',
            'plughw:audiocodec,0',
            filepath
        ])

    return jsonify({'status': 'ok', 'filename': filename})


@app.route('/stop')
def stop():
    global current_process

    if current_process:
        current_process.kill()
        current_process = None

    subprocess.run(['pkill', '-9', 'mpg123'])

    return jsonify({'status': 'stopped'})


@app.route('/files')
def list_files():
    metadata = get_metadata()
    files = []
    
    for f in os.listdir(CACHE_DIR):
        if f.endswith('.mp3'):
            filepath = os.path.join(CACHE_DIR, f)
            if os.path.isfile(filepath):
                info = metadata.get(f, {'display_name': f, 'text': '', 'voice': ''})
                files.append({
                    'filename': f,
                    'display_name': info['display_name'],
                    'text': info.get('text', ''),
                    'voice': info.get('voice', ''),
                    'is_favorite': info.get('is_favorite', False),
                    'created_at': os.path.getctime(filepath)
                })
    
    files.sort(key=lambda x: (not x['is_favorite'], -x['created_at']))
    return jsonify({'files': files})


@app.route('/play-file', methods=['POST'])
def play_file():
    global current_process
    
    filename = request.form.get('filename')
    loop = request.form.get('loop') == 'true'
    interval = int(request.form.get('interval', 5))
    
    if not filename:
        return jsonify({'status': 'error', 'message': '请选择文件'})
    
    filepath = os.path.join(CACHE_DIR, filename)
    
    if not os.path.exists(filepath):
        return jsonify({'status': 'error', 'message': '文件不存在'})
    
    if current_process:
        current_process.kill()
    
    subprocess.run(['pkill', '-9', 'mpg123'])
    
    if loop:
        current_process = subprocess.Popen([
            'bash',
            'player.sh',
            filepath,
            str(interval)
        ])
    else:
        current_process = subprocess.Popen([
            'mpg123',
            '-o',
            'alsa',
            '-a',
            'plughw:audiocodec,0',
            filepath
        ])
    
    metadata = get_metadata()
    display_name = metadata.get(filename, {}).get('display_name', filename)
    
    return jsonify({'status': 'ok', 'message': f'正在播放: {display_name}'})


@app.route('/rename-file', methods=['POST'])
def rename_file():
    filename = request.form.get('filename')
    new_name = request.form.get('new_name')
    
    if not filename or not new_name:
        return jsonify({'status': 'error', 'message': '参数错误'})
    
    metadata = get_metadata()
    
    if filename not in metadata:
        return jsonify({'status': 'error', 'message': '文件不存在'})
    
    metadata[filename]['display_name'] = new_name
    save_metadata(metadata)
    
    return jsonify({'status': 'ok', 'message': '重命名成功'})


@app.route('/toggle-favorite', methods=['POST'])
def toggle_favorite():
    filename = request.form.get('filename')
    
    if not filename:
        return jsonify({'status': 'error', 'message': '参数错误'})
    
    metadata = get_metadata()
    
    if filename not in metadata:
        return jsonify({'status': 'error', 'message': '文件不存在'})
    
    metadata[filename]['is_favorite'] = not metadata[filename].get('is_favorite', False)
    save_metadata(metadata)
    
    return jsonify({
        'status': 'ok',
        'is_favorite': metadata[filename]['is_favorite'],
        'message': '收藏成功' if metadata[filename]['is_favorite'] else '取消收藏成功'
    })


@app.route('/delete-file', methods=['POST'])
def delete_file():
    global current_process
    
    filename = request.form.get('filename')
    
    if not filename:
        return jsonify({'status': 'error', 'message': '请选择文件'})
    
    filepath = os.path.join(CACHE_DIR, filename)
    
    if not os.path.exists(filepath):
        return jsonify({'status': 'error', 'message': '文件不存在'})
    
    if current_process:
        try:
            current_process.kill()
            current_process = None
        except:
            pass
    
    subprocess.run(['pkill', '-9', 'mpg123'])
    
    os.remove(filepath)
    
    metadata = get_metadata()
    if filename in metadata:
        del metadata[filename]
        save_metadata(metadata)
    
    return jsonify({'status': 'ok', 'message': '删除成功'})


if __name__ == '__main__':
    if not os.path.exists(CACHE_DIR):
        os.makedirs(CACHE_DIR)
    app.run(host='0.0.0.0', port=5000)