import logging
import re
import subprocess
import sys
from argparse import ArgumentParser, FileType
import time
import os

from app.bcut_asr import BcutASR, ResultStateEnum, APIError
from ui import ConstData

logging.basicConfig(
    format="%(asctime)s - [%(levelname)s] %(message)s",
    level=logging.INFO,
)

INFILE_FMT = ["flac", "aac", "m4a", "mp3", "wav"]
OUTFILE_FMT = ["srt", "json", "lrc", "txt"]

parser = ArgumentParser(
    prog="bcut-asr",
    description="必剪语音识别\n",
    epilog=f"支持输入音频格式: {', '.join(INFILE_FMT)}  支持自动调用ffmpeg提取视频伴音",
)
parser.add_argument(
    "-f", "--format", nargs="?", default="srt", choices=OUTFILE_FMT, help="输出字幕格式"
)
parser.add_argument(
    "-i",
    "--interval",
    nargs="?",
    type=float,
    default="1.0",
    metavar="1.0",
    help="任务状态轮询间隔(秒)",
)
parser.add_argument("input", type=FileType("rb"), help="输入媒体文件")
parser.add_argument(
    "output",
    nargs="?",
    type=FileType("w", encoding="utf8"),
    help="输出字幕文件, 可stdout",
)


def get_audio_codec(file_path):
    """
    调用ffmpeg获取音频编码类型（如ac3、aac、mp3等）
    :param file_path: 视频文件路径
    :return: 音频编码字符串（如"ac3"），失败则返回None
    """
    try:
        # 执行ffmpeg -i命令，捕获stderr输出
        result = subprocess.run(
            ['ffmpeg', '-i', file_path],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            encoding='gbk',   # Windows 推荐
            errors='ignore',  # 防止乱码崩
            shell=False
        )
        # 从stderr中提取音频编码信息（正则匹配）
        # 匹配模式：Audio: 编码名称（如 "Audio: ac3" 或 "Audio: aac (LC)"）
        match = re.search(r'Audio: (\w+)', result.stderr)
        if match:
            return match.group(1).lower()  # 返回小写编码（如ac3、aac）
        else:
            print("未找到音频流信息")
            return None
    except Exception as e:
        print(f"获取音频编码失败：{e}")
        return None


def run(infile_name: str):
    full_name_os = os.path.basename(infile_name)
    codec = get_audio_codec(infile_name)
    if not codec:
        return None
    print(f'codec:{codec}')
    output_audio = f"{os.path.dirname(infile_name)}/{full_name_os.rsplit('.', 1)[-2]}.aac"
    # result = subprocess.run(
    #     ['ffmpeg', '-i', infile_name],
    #     stdout=subprocess.PIPE,
    #     stderr=subprocess.PIPE,
    #     text=True,
    #     shell=True  # Windows系统处理特殊路径需要
    # )
    # print(result.stderr)
    if ConstData.cut_stop:
        return None
    if not os.path.exists(output_audio):
        if codec != 'aac':
            command = [
                "ffmpeg",
                "-i", infile_name,  # 输入视频文件
                "-vn",
                "-acodec", "aac",  # 重新编码为 AAC
                "-b:a", "128k",  # 比特率（可选）
                output_audio
            ]
        else:
            command = [
                'ffmpeg',
                '-i', infile_name,
                '-vn',  # 忽略视频流
                '-acodec', 'copy',  # 直接复制音频流（无损快速）
                output_audio
            ]
        print(command)
        subprocess.run(command, check=True)
    interval = 1.0
    # 开始执行转换逻辑
    asr = BcutASR()
    asr.set_data(file=output_audio, data_fmt="aac")
    try:
        # 上传文件
        asr.upload()
        if ConstData.cut_stop:
            return None
        # 创建任务
        task_id = asr.create_task()
        while True:
            if ConstData.cut_stop:
                return None
            # 轮询检查任务状态
            task_resp = asr.result(task_id=task_id)
            if task_resp.state == ResultStateEnum.STOP:
                logging.info(f"等待识别开始")
            elif task_resp.state == ResultStateEnum.RUNING:
                logging.info(f"识别中 {task_resp.remark}")
            elif task_resp.state == ResultStateEnum.ERROR:
                logging.error(f"识别失败 {task_resp.remark}")
            elif task_resp.state == ResultStateEnum.COMPLETE:
                logging.info(f"识别成功")
                outfile_name = f"{output_audio.rsplit('.', 1)[-2]}.srt"
                outfile = open(outfile_name, "w", encoding="utf8")
                # 识别成功, 回读字幕数据
                result = task_resp.parse()
                break
            time.sleep(interval)
        if not result.has_data():
            logging.error("未识别到语音")
            raise Exception("未识别到语音")
        outfile.write(result.to_srt())
        outfile.close()
        logging.info(f"转换成功: {outfile_name}")
    except APIError as err:
        logging.error(f"接口错误: {err.__str__()}")
        raise Exception("接口错误")


def run_mp3(infile_name: str,data_fmt="mp3"):
    interval = 1.0
    # 开始执行转换逻辑
    asr = BcutASR()
    asr.set_data(file=infile_name, data_fmt=data_fmt)
    try:
        # 上传文件
        asr.upload()
        if ConstData.cut_stop:
            return None
        # 创建任务
        task_id = asr.create_task()
        while True:
            if ConstData.cut_stop:
                return None
            # 轮询检查任务状态
            task_resp = asr.result(task_id=task_id)
            if task_resp.state == ResultStateEnum.STOP:
                logging.info(f"等待识别开始")
            elif task_resp.state == ResultStateEnum.RUNING:
                logging.info(f"识别中 {task_resp.remark}")
            elif task_resp.state == ResultStateEnum.ERROR:
                logging.error(f"识别失败 {task_resp.remark}")
            elif task_resp.state == ResultStateEnum.COMPLETE:
                logging.info(f"识别成功")
                outfile_name = f"{infile_name.rsplit('.', 1)[-2]}.srt"
                outfile = open(outfile_name, "w", encoding="utf8")
                # 识别成功, 回读字幕数据
                result = task_resp.parse()
                break
            time.sleep(interval)
        if not result.has_data():
            logging.error("未识别到语音")
            raise Exception("未识别到语音")
        outfile.write(result.to_srt())
        outfile.close()
        logging.info(f"转换成功: {outfile_name}")
    except APIError as err:
        logging.error(f"接口错误: {err.__str__()}")
        raise Exception("接口错误")


def main():
    infile_name = "D:\\work\\python\\SplitVideo\\test.mp4"
    output_audio = "D:\\work\\python\\SplitVideo\\test.aac"

    command = [
        "ffmpeg",
        "-i", infile_name,  # 输入视频文件
        "-vn",  # 去掉视频流，只保留音频
        "-acodec", "copy",  # 不重新编码，直接拷贝音频流
        output_audio
    ]
    subprocess.run(command, check=True)
    interval = 1.0
    # 开始执行转换逻辑
    asr = BcutASR()
    asr.set_data(file=output_audio, data_fmt="aac")
    try:
        # 上传文件
        asr.upload()
        # 创建任务
        task_id = asr.create_task()
        while True:
            # 轮询检查任务状态
            task_resp = asr.result(task_id=task_id)
            if task_resp.state == ResultStateEnum.STOP:
                logging.info(f"等待识别开始")
            elif task_resp.state == ResultStateEnum.RUNING:
                logging.info(f"识别中 {task_resp.remark}")
            elif task_resp.state == ResultStateEnum.ERROR:
                logging.error(f"识别失败 {task_resp.remark}")
            elif task_resp.state == ResultStateEnum.COMPLETE:
                logging.info(f"识别成功")
                outfile_name = f"{output_audio.rsplit('.', 1)[-2]}.srt"
                outfile = open(outfile_name, "w", encoding="utf8")
                # 识别成功, 回读字幕数据
                result = task_resp.parse()
                break
            time.sleep(interval)
        if not result.has_data():
            logging.error("未识别到语音")
            return -1
        outfile.write(result.to_srt())
        outfile.close()
        logging.info(f"转换成功: {outfile_name}")
    except APIError as err:
        logging.error(f"接口错误: {err.__str__()}")
        return -1


if __name__ == "__main__":
    sys.exit(main())
