# core/audio_analysis.py
import os
import json
import numpy as np
import librosa
import sys

def extract_waveform_data(file_path, samples=100):
    """
    读取音频文件，提取归一化后的波形振幅数据点。
    @param file_path: 音频文件的完整路径。
    @param samples: 目标波形图所需的点数 (例如 100 个点)。
    @return: 包含 samples 个点的浮点数列表。
    """
    try:
        # 1. 加载音频数据 (只加载单声道)
        y, sr = librosa.load(file_path, sr=None, mono=True)
        
        # 降采样：将所有数据点降维到 'samples' 个点
        segment_length = len(y) // samples
        if segment_length == 0:
            # 文件太短，直接返回所有点
            return y.tolist()
            
        data_points = []
        for i in range(samples):
            start = i * segment_length
            end = (i + 1) * segment_length
            segment = y[start:end]
            
            # 提取该段的最大绝对振幅
            max_abs_amplitude = np.max(np.abs(segment))
            data_points.append(float(max_abs_amplitude))  # 确保是 float 类型，JSON 可序列化
            
        return data_points
        
    except Exception as e:
        # 如果音频文件损坏或格式不支持
        return []

def read_cached_records(fixed_cache_filepath):
    """
    安全地讀取緩存文件。
    返回一個字典，鍵是 full_path，值是文件記錄字典。
    """
    if not os.path.exists(fixed_cache_filepath):
        # 如果文件不存在，返回空的數據結構
        return {}
    try:
        with open(fixed_cache_filepath, 'r', encoding='utf-8') as f:
            data = json.load(f)
            # 從緩存的 records 列表中創建一個以 full_path 為鍵的字典 (用於快速查找和去重)
            records_map = {
                record["full_path"]: record 
                for record in data.get("records", [])
            }
            return records_map
    except Exception as e:
        # 緩存文件損壞，警告並返回空數據，避免崩潰
        print(f"WARNING: 讀取緩存文件失敗或 JSON 格式錯誤: {e}", file=sys.stderr)
        return {}

def get_audio_data_handler(fixed_cache_filepath) -> dict:
    """讀取固定 JSON 文件中的緩存數據"""
    try:
        # 檢查固定文件是否存在
        if os.path.exists(fixed_cache_filepath):
            with open(fixed_cache_filepath, 'r', encoding='utf-8') as f:
                cached_data = json.load(f)
            return {
                "status": "success",
                "message": "成功讀取緩存數據。",
                "data": cached_data  # 返回整個緩存數據結構
            }
        else:
            # 如果文件不存在，返回空列表
            return {
                "status": "success",
                "message": "無歷史緩存數據。",
                "data": {"records": []}
            }
    except Exception as e:
        # 捕獲讀取錯誤（例如 JSON 格式損壞）
        return {
            "status": "error",
            "message": f"讀取緩存文件失敗: {str(e)}",
            "data": {}
        }

def analyze_dir_handler(directory_path: str, fixed_cache_filepath, data_cache_dir) -> dict:
    """處理目錄分析請求"""
    # 驗證路徑安全性
    if not directory_path or not os.path.exists(directory_path):
        raise FileNotFoundError(f"目錄不存在: {directory_path}")
    
    # 獲取 {full_path: record} 字典，用於快速去重
    master_records_map = read_cached_records(fixed_cache_filepath) 
    new_files_count = 0
    
    try:
        # 遍歷目錄下的所有文件和文件夾
        for filename in os.listdir(directory_path):
            full_path = os.path.join(directory_path, filename)
            
            # **只記錄文件，忽略子目錄**
            if os.path.isfile(full_path):
                # 1. 確保路徑是絕對且規範的
                safe_full_path_native = os.path.abspath(os.path.normpath(full_path))
                # 2. 將 Windows 的 \ 替換為 /，讓前端處理更方便
                safe_full_path = safe_full_path_native.replace('\\', '/')
                
                # 3. 檢查是否已存在於緩存中
                if safe_full_path not in master_records_map:
                    base_name, ext = os.path.splitext(filename)
                    is_audio = ext.lower() in ('.wav', '.mp3')
                    
                    # === 新增：波形数据提取 ===
                    waveform_data = []
                    if is_audio:
                        waveform_data = extract_waveform_data(safe_full_path, samples=300) 
                    # =========================
    
                    # 創建文件記錄字典
                    record =  {
                        "full_path": safe_full_path,
                        "name_no_ext": base_name,
                        "extension": ext.lower(),
                        "is_audio": is_audio,
                        "waveform": waveform_data
                    }
                    # 添加到主字典中
                    master_records_map[safe_full_path] = record
                    new_files_count +=  1
    except PermissionError:
        raise PermissionError(f"无权访问该目录: {directory_path}")
    except Exception as e:
        raise Exception(f"分析目录时发生未知错误: {str(e)}") 

    # 將 master_records_map 轉換回列表 (這是最終要存儲的格式)
    final_records_list = list(master_records_map.values())
    audio_file_records = [r for r in final_records_list if r['is_audio']]
    
    try:
        os.makedirs(data_cache_dir, exist_ok=True)
        data_to_save = {
            "last_scanned_path": directory_path,
            "total_records": len(audio_file_records),
            "records": audio_file_records 
        }
        with open(fixed_cache_filepath, 'w', encoding='utf-8') as f:
            json.dump(data_to_save, f, ensure_ascii=False, indent=4)
            
    except Exception as e:
        print(f"WARNING: 緩存寫入失敗: {e}", file=sys.stderr)

    return {
        "status": "success",
        "message": f"成功掃描目錄，新增 {new_files_count} 個文件。總數：{len(final_records_list)}。",
        "data": {
            "cache_file_path": fixed_cache_filepath.replace('\\', '/'),
            "total_records": len(final_records_list),
            "new_files_count": new_files_count,
            "all_file_records": final_records_list,
            "audio_files_count": len(audio_file_records)        
        }
    }