#!/opt/homebrew/bin/python3.11
"""
Interactive Speaker Audio Player - 交互式說話人語音播放器
可以選擇播放哪個說話人的哪些片段
"""

import json
import subprocess
import tempfile
import os
from pathlib import Path
from typing import List, Dict


def load_asrx_result(result_path: str) -> Dict:
    """載入 ASRX 結果"""
    with open(result_path, "r", encoding="utf-8") as f:
        return json.load(f)


def extract_and_play(audio_path: str, start_sec: float, end_sec: float) -> bool:
    """提取並播放音頻片段"""
    duration = end_sec - start_sec
    temp_file = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
    temp_path = temp_file.name
    temp_file.close()

    try:
        # 提取
        cmd = [
            "ffmpeg",
            "-y",
            "-loglevel",
            "quiet",
            "-i",
            audio_path,
            "-ss",
            str(start_sec),
            "-t",
            str(duration),
            "-acodec",
            "pcm_s16le",
            "-ar",
            "16000",
            "-ac",
            "1",
            temp_path,
        ]

        result = subprocess.run(cmd, capture_output=True)
        if result.returncode != 0:
            return False

        # 播放
        if os.path.exists("/usr/bin/afplay"):
            subprocess.run(["afplay", temp_path], capture_output=True)
        elif os.path.exists("/usr/bin/aplay"):
            subprocess.run(["aplay", temp_path], capture_output=True)
        else:
            print("  ⚠️  No audio player found")
            return False

        return True
    finally:
        if os.path.exists(temp_path):
            os.unlink(temp_path)


def show_menu(speaker_segments: Dict[str, List[Dict]], speaker_id: str):
    """顯示選單"""
    segs = speaker_segments[speaker_id]
    total_duration = sum(seg["duration"] for seg in segs)

    print(f"\n{'=' * 70}")
    print(f"🔊 {speaker_id}")
    print(f"{'=' * 70}")
    print(f"  Segments: {len(segs)}")
    print(
        f"  Total duration: {total_duration / 60:.1f} minutes ({total_duration:.1f}s)"
    )
    print(f"{'=' * 70}")

    # 顯示前 20 個片段
    for i, seg in enumerate(segs[:20], 1):
        start = seg["start"]
        end = seg["end"]
        duration = seg["duration"]
        print(
            f"  [{i:3d}] {speaker_id:12} | {start:7.2f}s - {end:7.2f}s  ({duration:5.2f}s)"
        )

    if len(segs) > 20:
        print(f"  ... and {len(segs) - 20} more segments")

    print(f"\n{'=' * 70}")
    print(f"Commands:")
    print(f"  [1-{min(20, len(segs))}]  Play specific segment")
    print(f"  all      Play all segments (may take a while)")
    print(f"  first N  Play first N segments")
    print(f"  next     Next speaker")
    print(f"  prev     Previous speaker")
    print(f"  list     List all speakers")
    print(f"  quit     Exit")
    print(f"{'=' * 70}")


def interactive_player(audio_path: str, result_path: str):
    """交互式播放器"""
    # 載入結果
    result = load_asrx_result(result_path)
    segments = result.get("segments", [])
    total_duration = result.get("total_duration", 0)

    # 分組
    speaker_segments = {}
    for seg in segments:
        speaker = seg["speaker"]
        if speaker not in speaker_segments:
            speaker_segments[speaker] = []
        speaker_segments[speaker].append(seg)

    # 排序
    for speaker in speaker_segments:
        speaker_segments[speaker].sort(key=lambda x: x["start"])

    # 說話人列表
    speakers = sorted(
        speaker_segments.keys(),
        key=lambda s: sum(seg["duration"] for seg in speaker_segments[s]),
        reverse=True,
    )

    current_speaker_idx = 0

    print(f"\n🎬 Speaker Audio Player")
    print(f"📁 Audio: {audio_path}")
    print(f"📊 Speakers: {len(speakers)}")
    print(f"{'=' * 70}")

    while True:
        current_speaker = speakers[current_speaker_idx]
        show_menu(speaker_segments, current_speaker)

        try:
            cmd = input(f"\n▶️  {current_speaker} > ").strip().lower()
        except (EOFError, KeyboardInterrupt):
            print("\n\nExiting...")
            break

        if not cmd:
            continue

        # 播放特定片段
        if cmd.isdigit():
            idx = int(cmd) - 1
            if 0 <= idx < len(speaker_segments[current_speaker]):
                seg = speaker_segments[current_speaker][idx]
                print(f"\n  🔊 {current_speaker} - Segment {idx + 1}")
                print(
                    f"  ⏱️  {seg['start']:.2f}s - {seg['end']:.2f}s ({seg['duration']:.2f}s)"
                )
                print(f"  ▶️  Playing...", end="", flush=True)
                if extract_and_play(audio_path, seg["start"], seg["end"]):
                    print(" ✅ Done")
                else:
                    print(" ❌ Failed")
            else:
                print(
                    f"  Invalid segment number (1-{len(speaker_segments[current_speaker])})"
                )

        # 播放所有
        elif cmd == "all":
            print(
                f"\n  🔊 {current_speaker} - Playing all {len(speaker_segments[current_speaker])} segments..."
            )
            print("=" * 70)
            for i, seg in enumerate(speaker_segments[current_speaker], 1):
                print(
                    f"  [{i:3d}/{len(speaker_segments[current_speaker])}] {current_speaker} | "
                    + f"{seg['start']:7.2f}s - {seg['end']:7.2f}s ({seg['duration']:5.2f}s)",
                    end="",
                    flush=True,
                )
                if extract_and_play(audio_path, seg["start"], seg["end"]):
                    print(" ✅")
                else:
                    print(" ❌")
            print("=" * 70)

        # 播放前 N 個
        elif cmd.startswith("first "):
            try:
                n = int(cmd.split()[1])
                print(f"\n  🔊 {current_speaker} - Playing first {n} segments...")
                print("=" * 70)
                for i, seg in enumerate(speaker_segments[current_speaker][:n], 1):
                    print(
                        f"  [{i:3d}/{n}] {current_speaker} | "
                        + f"{seg['start']:7.2f}s - {seg['end']:7.2f}s ({seg['duration']:5.2f}s)",
                        end="",
                        flush=True,
                    )
                    if extract_and_play(audio_path, seg["start"], seg["end"]):
                        print(" ✅")
                    else:
                        print(" ❌")
                print("=" * 70)
            except (IndexError, ValueError):
                print("  Usage: first N")

        # 下一個說話人
        elif cmd == "next":
            current_speaker_idx = (current_speaker_idx + 1) % len(speakers)

        # 上一個說話人
        elif cmd == "prev":
            current_speaker_idx = (current_speaker_idx - 1) % len(speakers)

        # 列出所有說話人
        elif cmd == "list":
            print(f"\n{'=' * 70}")
            print(f"📢 All speakers:")
            print(f"{'=' * 70}")
            for i, speaker in enumerate(speakers, 1):
                segs = speaker_segments[speaker]
                total_dur = sum(seg["duration"] for seg in segs)
                pct = total_dur / total_duration * 100 if total_duration > 0 else 0
                print(
                    f"  {i:2d}. 🔊 {speaker:12} | {len(segs):4d} segments, "
                    + f"{total_dur:7.1f}s ({pct:5.1f}%)"
                )
            print(f"{'=' * 70}")
            print(f"  Current: 🔊 {speakers[current_speaker_idx]}")
            print(f"{'=' * 70}")

        # 退出
        elif cmd == "quit" or cmd == "exit" or cmd == "q":
            print("\nExiting...")
            break

        else:
            print(f"  Unknown command: {cmd}")


def main():
    import argparse

    parser = argparse.ArgumentParser(description="Interactive Speaker Audio Player")
    parser.add_argument("audio_path", help="原始音頻文件路徑")
    parser.add_argument("result_path", help="ASRX 結果 JSON 路徑")

    args = parser.parse_args()

    if not Path(args.audio_path).exists():
        print(f"Error: Audio file not found: {args.audio_path}")
        return

    if not Path(args.result_path).exists():
        print(f"Error: Result file not found: {args.result_path}")
        return

    interactive_player(args.audio_path, args.result_path)


if __name__ == "__main__":
    main()
