import os
import random
import sys

import pandas as pd
import torchaudio
from pathlib import Path
from tqdm import tqdm


workspace_dir = Path(__file__).parent.parent.parent
sys.path.append(str(workspace_dir.joinpath('src')))
# sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from handle.text_handle import process_text
from tokenizer import ASRTokenizer

# 读取 TSV
# df = pd.read_csv(workspace_dir / '.data/ug/train.tsv', sep='\t')

# # 计算每个音频的时长（秒）
# durations = []
# for audio_path in tqdm(workspace_dir / '.data/ug/clips' / df['path'], desc="计算音频时长"):
#     try:
#         # 获取音频信息（不加载整个文件，速度快）
#         info = torchaudio.info(audio_path)
#         duration = info.num_frames / info.sample_rate
#         durations.append(duration)
#     except Exception as e:
#         print(f"读取失败: {audio_path}, 错误: {e}")
#         durations.append(None)

# # 添加到 DataFrame
# df['duration'] = durations

# # 统计
# print(df['duration'].describe())
# print(f"超过20秒的样本: {(df['duration'] > 20).sum()}")

# 保存结果（可选）
# df.to_csv('data/audio/train_with_duration.tsv', sep='\t', index=False)

# audio_path = workspace_dir / '.data/ug/clips/common_voice_ug_40252722.mp3'
# info = torchaudio.info(audio_path)
# print("info:", info)
import pandas as pd
import torch
import torchaudio
import numpy as np
from pathlib import Path
from tqdm import tqdm

def analyze_audio_quality(audio_path, sample_rate_target=16000):
    """
    评估音频质量，返回多个指标
    """
    try:
        # 加载音频
        waveform, sr = torchaudio.load(str(audio_path))
        
        # 重采样 + 单声道
        if sr != sample_rate_target:
            resampler = torchaudio.transforms.Resample(sr, sample_rate_target)
            waveform = resampler(waveform)
        if waveform.shape[0] > 1:
            waveform = waveform.mean(dim=0, keepdim=True)
        
        # 归一化
        max_val = waveform.abs().max()
        if max_val > 0:
            waveform = waveform / max_val
        
        # ===== 指标 1: 静音比例 =====
        silence_threshold = 0.01
        is_silence = waveform.abs() < silence_threshold
        silence_ratio = is_silence.float().mean().item()
        
        # ===== 指标 2: 动态范围 =====
        frame_len = int(0.025 * sample_rate_target)  # 25ms
        hop_len = int(0.010 * sample_rate_target)    # 10ms
        
        num_frames = (waveform.shape[1] - frame_len) // hop_len + 1
        if num_frames <= 0:
            return None
            
        energies = []
        for i in range(num_frames):
            start = i * hop_len
            frame = waveform[:, start:start + frame_len]
            rms = frame.pow(2).mean().sqrt().item()
            energies.append(rms)
        
        energies = np.array(energies)
        energies = np.clip(energies, 1e-10, None)
        
        log_energies = 20 * np.log10(energies)
        dynamic_range = log_energies.max() - log_energies.min()
        
        # ===== 指标 3: 语音活跃度 =====
        energy_threshold = np.percentile(energies, 30)
        voice_ratio = (energies > energy_threshold).mean()
        
        # ===== 指标 4: 频谱中心频率 =====
        spec_transform = torchaudio.transforms.Spectrogram(n_fft=512)
        spec = spec_transform(waveform)  # [1, freq, time]
        
        # 用 torch 计算，避免 numpy axis 问题
        freqs = torch.fft.rfftfreq(512, d=1.0/sample_rate_target)
        spec_mean = spec.mean(dim=-1).squeeze()  # [freq_bins] torch 张量
        
        # 确保类型一致，用 torch 计算
        spectral_centroid = (freqs * spec_mean).sum() / (spec_mean.sum() + 1e-10)
        spectral_centroid = spectral_centroid.item()
        
        # ===== 指标 5: 频谱通量 =====
        spec_np = spec.squeeze().numpy()  # [freq, time]
        flux = np.abs(np.diff(spec_np, axis=1)).mean()
        
        return {
            'duration': waveform.shape[1] / sample_rate_target,
            'silence_ratio': silence_ratio,
            'dynamic_range_db': float(dynamic_range),
            'voice_ratio': float(voice_ratio),
            'spectral_centroid': spectral_centroid,
            'spectral_flux': float(flux),
            'energy_std': float(energies.std()),
        }
        
    except Exception as e:
        print(f"失败: {audio_path}, {e}")
        return None


# ===== 批量处理 =====
# df = pd.read_csv(workspace_dir / '.data/ug/train.tsv', sep='\t')

# results = []
# for _, row in tqdm(df.iterrows(), total=len(df), desc="评估音频质量"):
#     audio_path = workspace_dir / '.data/ug/clips'  / row['path']
#     metrics = analyze_audio_quality(audio_path)
#     if metrics:
#         metrics['path'] = row['path']
#         results.append(metrics)

# # 汇总
# quality_df = pd.DataFrame(results)
# print(quality_df.describe())


# # ===== 质量评分 =====
# def score_quality(row):
#     score = 100
    
#     if row['silence_ratio'] > 0.5:
#         score -= 30
#     elif row['silence_ratio'] > 0.3:
#         score -= 15
    
#     if row['dynamic_range_db'] < 10:
#         score -= 25
#     elif row['dynamic_range_db'] < 20:
#         score -= 10
    
#     if row['voice_ratio'] < 0.3:
#         score -= 20
    
#     if row['spectral_centroid'] > 4000:
#         score -= 15
    
#     return max(0, score)

# quality_df['quality_score'] = quality_df.apply(score_quality, axis=1)

# quality_df['grade'] = pd.cut(
#     quality_df['quality_score'],
#     bins=[0, 40, 60, 80, 100],
#     labels=['差(弃用)', '较差', '一般', '良好']
# )

# print("\n质量分级统计:")
# print(quality_df['grade'].value_counts())

# # 保存结果
# quality_df.to_csv('audio_quality_analysis.csv', index=False)
# print("\n结果已保存到 audio_quality_analysis.csv")


# Test
# text = "مەن مەكتەپكە باردىم"
# text = "ئاۋۋال كومپىيوتىرنى بىر كۆرسەم شۇنىڭغا قاراپ ماسلاشتۇرسام بوللاتتى"
text = "قاپاقنى پۇلغا ئالماي، باراڭنى پۇلغا ئاپتۇ"
# text = "ئامېىقى جاھان گۈرلىكىە قارشتۇرۇپ چوكشەڭگە ياردەم بېرىش ئۇرۇشىنىڭ ئلۇغ غەلبىسى جۇڭگو خەلقى ئورندىن دەستۇرغاندىكىن، دۇنيانىڭ شەرقىدە قەت كۆتۈرگەنلكىنى خىتاب لامىسى."
# text = "ئاۋسترالىيە"

text = "	ھەر قانداق ئىشتا كىشىلەر بىلەن كېڭىشىش كېرەك. لېكىن كۆڭۈل تارتقان ئىشنى قىلىۋېرىش كېرەك."
text = "\" 15 يىل بۇرۇن مەن بىلەن سەي چۇڭشىن (ئالى بابانىڭ قۇرغۇچىسىدىن بىرى) ئامېرىكىغا بېرىپ 30 نەچچە مەبلەغ سالغۇچى شىركەتلەر بىلەن كۆرۈشكىنىمىزدە ئۇلار بىزنى رەت قىلىپ ئىشىك سىرتىدا قالدۇرغاندى. ھېچكىم بىزگە ۋە كەلگۈسىمىزگە ئىشەنمىگەن ئىدى، ھېچكىممۇ بىزنىڭ ھازىر 300 مىليارد سودىنى تاماملىيالايدىغانلىقىمىزنى ئويلاپ خىيالىغىمۇ كەلتۈرمىگەن ئىدى.\" ئالى بابانىنىڭ ئورگىنى تەرىپىدىن ئىشلەنگەن ئىگىلىك تىكلەش ھۆججەتلىك فىلىمى \" بۇ چۈش ئەمەس\" نىڭ باش قىسمىدا مۇنداق بىر داڭلىق سۆز چىقىدۇ:\" مەن تاغدىن ئۆتكەن ۋاقتىمدا تاغ ماڭا گەپ قىلمىدى، مەن دېڭىزنى كېچىپ ئۆتكىنىمدە دېڭىز ماڭا گەپ قىلمىدى.\" بۇ فىلىمنىڭ قوشۇمچە ئىسمى بولسا \" مايۈن ۋە ئۇنىڭ مەڭگۈلۈك ' ياش ئالى'سى\" بولۇپ، ھەرخىل خەتەر ۋە قىيىنلىقنى بىرمۇ بىر يەڭگەن مايۈن ۋە ئۇنىڭ ئالى بابا قوشۇنىدىكى ھەمكارلاشقۇچىلىرىنىڭ قەيسەر كەچمىشى جانلىق بايان قىلىنغان."
# text = "يۆ جيەنتاۋ يېقىنقى بىر مەزگىلدە، خىزمەتداشلىرى بىلەن نۇرغۇن قىيىنچىلىققا ئۇچرىغان شوپۇرغا ياردەم قىلغانلىقىنى، شۇنداقلا يېمەكلىك ۋە سۇ يەتكۈزۈپ بەرگەنلىكىنى، ئەمما ئاياغ سوۋغا قىلىشى تۇنجى قېتىم ئىكەنلىكىنى، بۈگۈنكىسى 20 يىللىق ساقچىلىق جەريانىدا تۇنجى قېتىم شوپۇرغا ئاياغ سوۋغا قىلىشى ئىكەنلىكىنى ئېيتتى."
text = "يۆ جۇڭمىڭ مۇنداق دېدى: 2019- يىلى 12-ئايدا، مەملىكەتلىك خەلق قۇرۇلتىيى دائىمىي كومىتېتىنىڭ 44- قېتىملىق كومىتېت باشلىقلىرى يىغىنى مەملىكەتلىك خەلق قۇرۇلتىيى دائىمىي كومىتېتىنىڭ 2020-يىللىق قانۇن چىقىرىش خىزمىتى پىلانىنى پىرىنسىپ جەھەتتىن ماقۇللىدى، خىزمەت تەرتىپى بويىچە، 13-نۆۋەتلىك مەملىكەتلىك خەلق قۇرۇلتىيى 3-يىغىنىنىڭ روھى ۋە ۋەكىللەرنىڭ تەكلىپ-تەۋسىيەلىرىگە ئاساسەن پىلاننى تەڭشەش كېرەك. بۇ يىل 6-ئاينىڭ 1-كۈنى، 58-قېتىملىق كومىتېت باشلىقلىرى يىغىنى تەڭشەلگەندىن كېيىنكى يىللىق قانۇن چىقىرىش خىزمىتى پىلانىنى قاراپ چىقىپ ماقۇللىدى."
text = "	ئاشقازان-ئۈچەينىڭ لۆمۈلدىشىنى ئىلگىرى سۈرىدىغان دورىنى تاماقتىن بۇرۇن ئىستېمال قىلىش كېرەك."
# text = "مەن مەكتەپكە باردىم"
# text = "غەرىپئەللىرى"
# text = "ئىكەنلىكىنى، بۈگۈنكىسى 20 يىللىق ساقچىلىق جەريانىدا تۇنجى"
# text = "	يېزىدىكى كەڭ، ئازادە ئۆي، باغلىرىنى تاشلاپ، خەقنىڭ ھويلىسىدا قورۇنۇپ-ئەيمىنىپ يەر دەسسەپ يۈردى.	"
# text = "بۇ يىللىق ئەمگەكچىلەر بايرىمىدا، 1-مايدىن 5-مايغىچە جەمئىي بەش كۈن دەم ئېلىشقا قويۇپ بېرىلىدۇ. 9-ماي (شەنبە) نورمال خىزمەت قىلىنىدۇ. شۇنىڭ بىلەن بىر ۋاقىتتا، ئۈرۈمچى شەھىرى تىيانشان رايونى، سايباغ رايونى، داۋانچىڭ رايونى، ئۈرۈمچى ناھىيەسىدىكى ئوتتۇرا، باشلانغۇچ مەكتەپلەر 29-ئاپرېلدىن 30-ئاپرېلغىچە ئەتىيازلىق دەم ئېلىشقا قويۇپ بېرىدۇ؛ سانجى ئوبلاستىدىكى ئوتتۇرا، باشلانغۇچ مەكتەپلەرنىڭ ئەتىيازلىق دەم ئېلىشى ئۈچ كۈن بولۇپ، بۇنىڭ ئىچىدە ئىككى كۈن 29-، 30-ئاپرېلغا ئورۇنلاشتۇرۇلىدۇ، قالغان بىر كۈن 1-ئىيۇنغا ئورۇنلاشتۇرۇلىدۇ، قۇربان ھېيتلىق دەم ئېلىش بىلەن بىرلەشتۈرۈلۈپ، ئۇدا ئالتە كۈن دەم ئېلىنىدۇ."
# text = "ئەڭ يېڭى دەم ئېلىشقا قويۇپ بېرىش ئۇقتۇرۇشى! تەقەززالىق بىلەن كۈتكەن يەنە بىر دەم ئېلىش كېلەي دەپ قالدى! گوۋۇيۈەن بەنگۇڭتىڭىنىڭ «2025-يىللىق قىسمەن بايرام، دەم ئېلىش كۈنلىرىنى ئورۇنلاشتۇرۇش توغرىسىدىكى ئۇقتۇرۇشى»غا ئاساسەن، دۈەنۋۇ بايرىمىلىق دەم ئېلىشقا قويۇپ بېرىش ئورۇنلاشتۇرۇلۇشى تۆۋەندىكىچە: 5-ئاينىڭ 31-كۈنى (شەنبە)دىن 6-ئاينىڭ 2-كۈنىگىچە جەمئىي ئۈچ كۈن دەم ئېلىشقا قويۇپ بېرىلىدۇ! بۇ قېتىمقى دۈەنۋۇ بايرىمىلىق دەم ئېلىش ۋاقتى تەڭشەلمەيدۇ!"
# text = "مەن شۇ چاغدا چۈشۈمدىمۇ كۆرۈپ باقمىغان مۇنچىۋالا جىق قېرىنداشلىرىم، جىگەرلىرىمنىڭ بارلىقىدىن سۆيۈندۈم."
# text = "ئامېرىكا جاھان گىرلىكىگە قارشى تۇرۇپ، چاۋشەنگە ياردەم بىرىش ئۇرۇشىنىڭ ئۇلۇغ غەلبىسى، جۇڭگو خەلقى ئورۇندىن دەس تۇرغاندىنكىن دۇنيانىڭ شەرقىدە قەد كۆتۈرگەنلىكىنىڭ خىتاپنامىس"


# result = export_syllabize(text)
result = process_text(text)
print(f"Original: {text}")
print(f"Syllables: {result}")


tokenizer = ASRTokenizer(vocab_path=workspace_dir / 'config/asr_vocab.json')

print(text)
ids = tokenizer.encode(text=text)
# print(ids)
print('|'.join(tokenizer.decode([id]) for id in ids))