#!/opt/homebrew/bin/python3.11
"""
Speaker Player GUI - 說話人語音播放器（圖形界面）
使用 tkinter 顯示播放進度和 Speaker ID
"""

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

try:
    import tkinter as tk
    from tkinter import ttk, filedialog, messagebox

    HAS_TKINTER = True
except ImportError:
    HAS_TKINTER = False


class SpeakerPlayerGUI:
    """說話人語音播放器 GUI"""

    def __init__(self, root):
        self.root = root
        self.root.title("🎬 Speaker Audio Player - Face Integration")
        self.root.geometry("1100x800")

        # 數據
        self.audio_path = None
        self.result_path = None
        self.face_path = None
        self.result_data = None
        self.face_data = None
        self.integrated_data = None
        self.speaker_segments = {}
        self.speakers = []
        self.current_speaker_idx = 0
        self.is_playing = False
        self.stop_flag = False

        # 創建界面
        self.create_widgets()

    def create_widgets(self):
        """創建界面組件"""
        # 頂部：文件選擇
        top_frame = ttk.Frame(self.root, padding="10")
        top_frame.pack(fill=tk.X)

        ttk.Label(top_frame, text="📁 Audio:").pack(side=tk.LEFT)
        self.audio_label = ttk.Label(top_frame, text="未選擇", width=50)
        self.audio_label.pack(side=tk.LEFT, padx=5)
        ttk.Button(top_frame, text="選擇音頻", command=self.select_audio).pack(
            side=tk.LEFT, padx=5
        )

        ttk.Label(top_frame, text="  📊 Result:").pack(side=tk.LEFT, padx=(20, 0))
        self.result_label = ttk.Label(top_frame, text="未選擇", width=50)
        self.result_label.pack(side=tk.LEFT, padx=5)
        ttk.Button(top_frame, text="選擇結果", command=self.select_result).pack(
            side=tk.LEFT, padx=5
        )

        # 中間：說話人列表和片段列表
        mid_frame = ttk.Frame(self.root, padding="10")
        mid_frame.pack(fill=tk.BOTH, expand=True)

        # 左側：說話人列表
        left_frame = ttk.LabelFrame(mid_frame, text="📢 說話人列表", padding="10")
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=False)

        self.speaker_listbox = tk.Listbox(
            left_frame, width=35, height=20, font=("Arial", 11)
        )
        self.speaker_listbox.pack(fill=tk.BOTH, expand=True)
        self.speaker_listbox.bind("<<ListboxSelect>>", self.on_speaker_select)

        # 右側：片段列表
        right_frame = ttk.LabelFrame(mid_frame, text="🎵 語音片段", padding="10")
        right_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10)

        # 片段列表（带滚动条）
        list_frame = ttk.Frame(right_frame)
        list_frame.pack(fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(list_frame)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        self.segment_listbox = tk.Listbox(
            list_frame,
            width=50,
            height=20,
            font=("Courier", 10),
            yscrollcommand=scrollbar.set,
        )
        self.segment_listbox.pack(fill=tk.BOTH, expand=True)
        scrollbar.config(command=self.segment_listbox.yview)

        self.segment_listbox.bind("<Double-Button-1>", self.on_segment_double_click)

        # 底部：播放控制和進度
        bottom_frame = ttk.Frame(self.root, padding="10")
        bottom_frame.pack(fill=tk.X)

        # 播放控制
        control_frame = ttk.Frame(bottom_frame)
        control_frame.pack(fill=tk.X)

        self.play_button = ttk.Button(
            control_frame, text="▶️ 播放所選", command=self.play_selected, width=15
        )
        self.play_button.pack(side=tk.LEFT, padx=5)

        self.stop_button = ttk.Button(
            control_frame, text="⏹️ 停止", command=self.stop_playing, width=10
        )
        self.stop_button.pack(side=tk.LEFT, padx=5)
        self.stop_button.config(state=tk.DISABLED)

        self.play_all_button = ttk.Button(
            control_frame, text="▶️▶️ 播放全部", command=self.play_all, width=15
        )
        self.play_all_button.pack(side=tk.LEFT, padx=5)

        # 進度條
        progress_frame = ttk.Frame(bottom_frame)
        progress_frame.pack(fill=tk.X, pady=(10, 0))

        ttk.Label(progress_frame, text="⏱️ 進度:").pack(side=tk.LEFT)
        self.progress_bar = ttk.Progressbar(progress_frame, mode="determinate")
        self.progress_bar.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=10)

        self.progress_label = ttk.Label(progress_frame, text="0:00 / 0:00", width=20)
        self.progress_label.pack(side=tk.LEFT)

        # 狀態欄
        self.status_label = ttk.Label(
            bottom_frame, text="就緒", relief=tk.SUNKEN, anchor=tk.W
        )
        self.status_label.pack(fill=tk.X, pady=(10, 0))

    def select_audio(self):
        """選擇音頻文件"""
        filename = filedialog.askopenfilename(
            title="選擇音頻文件",
            filetypes=[("WAV files", "*.wav"), ("All files", "*.*")],
        )
        if filename:
            self.audio_path = filename
            self.audio_label.config(text=Path(filename).name)
            self.check_ready()

    def select_result(self):
        """選擇結果文件"""
        filename = filedialog.askopenfilename(
            title="選擇 ASRX 結果文件",
            filetypes=[("JSON files", "*.json"), ("All files", "*.*")],
        )
        if filename:
            self.result_path = filename
            self.result_label.config(text=Path(filename).name)
            self.load_result()
            self.check_ready()

    def load_result(self):
        """載入 ASRX 結果"""
        try:
            with open(self.result_path, "r", encoding="utf-8") as f:
                self.result_data = json.load(f)

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

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

            # 說話人列表（按時長排序）
            self.speakers = sorted(
                self.speaker_segments.keys(),
                key=lambda s: sum(seg["duration"] for seg in self.speaker_segments[s]),
                reverse=True,
            )

            # 更新列表框
            self.speaker_listbox.delete(0, tk.END)
            for speaker in self.speakers:
                segs = self.speaker_segments[speaker]
                total_dur = sum(seg["duration"] for seg in segs)
                total_dur_min = total_dur / 60
                self.speaker_listbox.insert(
                    tk.END,
                    f"🔊 {speaker:12} | {len(segs):4d}段 | {total_dur_min:5.1f}分鐘",
                )

            self.status_label.config(
                text=f"載入成功：{len(self.speakers)} 個說話人，{len(self.result_data.get('segments', []))} 個片段"
            )

        except Exception as e:
            messagebox.showerror("錯誤", f"載入結果文件失敗：{e}")
            self.result_path = None
            self.result_label.config(text="載入失敗")

    def check_ready(self):
        """檢查是否就緒"""
        if self.audio_path and self.result_path:
            self.status_label.config(text="✅ 就緒 - 請選擇說話人並播放")
            self.play_button.config(state=tk.NORMAL)
            self.play_all_button.config(state=tk.NORMAL)
        else:
            self.status_label.config(text="⚠️ 請選擇音頻和結果文件")
            self.play_button.config(state=tk.DISABLED)
            self.play_all_button.config(state=tk.DISABLED)

    def on_speaker_select(self, event):
        """說話人選擇事件"""
        selection = self.speaker_listbox.curselection()
        if not selection:
            return

        self.current_speaker_idx = selection[0]
        speaker = self.speakers[self.current_speaker_idx]

        # 更新片段列表
        self.segment_listbox.delete(0, tk.END)
        for i, seg in enumerate(self.speaker_segments[speaker], 1):
            start = seg["start"]
            end = seg["end"]
            duration = seg["duration"]
            self.segment_listbox.insert(
                tk.END,
                f"[{i:4d}] {speaker:12} | {start:7.2f}s - {end:7.2f}s ({duration:5.2f}s)",
            )

        self.status_label.config(
            text=f"選擇：{speaker} - {len(self.speaker_segments[speaker])} 個片段"
        )

    def on_segment_double_click(self, event):
        """片段雙擊事件"""
        self.play_selected()

    def extract_and_play(self, 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",
                self.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:
                return False

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

    def play_segment(self, speaker: str, seg: dict, seg_idx: int, total: int):
        """播放單個片段"""
        if self.stop_flag:
            return False

        start = seg["start"]
        end = seg["end"]
        duration = seg["duration"]

        # 更新 UI
        self.root.after(
            0,
            lambda: self.status_label.config(
                text=f"▶️  {speaker} [{seg_idx}/{total}] {start:.2f}s - {end:.2f}s"
            ),
        )

        # 更新進度
        progress = (seg_idx / total) * 100
        self.root.after(0, lambda: self.progress_bar.config(value=progress))
        self.root.after(
            0, lambda: self.progress_label.config(text=f"{seg_idx}:{total}")
        )

        # 播放
        if self.extract_and_play(start, end):
            return True
        else:
            self.root.after(
                0,
                lambda: messagebox.showwarning(
                    "警告", f"播放失敗：{speaker} [{seg_idx}]"
                ),
            )
            return True

    def play_selected(self):
        """播放所選片段"""
        selection = self.segment_listbox.curselection()
        if not selection:
            # 如果沒選擇，播放第一個
            if self.speakers:
                speaker = self.speakers[self.current_speaker_idx]
                segs = self.speaker_segments[speaker]
                if segs:
                    self.play_all()
            return

        # 播放所選
        seg_idx = selection[0]
        speaker = self.speakers[self.current_speaker_idx]
        seg = self.speaker_segments[speaker][seg_idx]

        self.is_playing = True
        self.stop_flag = False
        self.play_button.config(state=tk.DISABLED)
        self.stop_button.config(state=tk.NORMAL)

        # 在後台線程播放
        def play_thread():
            success = self.play_segment(speaker, seg, seg_idx + 1, 1)
            self.root.after(0, lambda: self.on_play_done())

        thread = threading.Thread(target=play_thread, daemon=True)
        thread.start()

    def play_all(self):
        """播放所選說話人的所有片段"""
        if not self.speakers:
            return

        speaker = self.speakers[self.current_speaker_idx]
        segs = self.speaker_segments[speaker]

        if not segs:
            return

        self.is_playing = True
        self.stop_flag = False
        self.play_button.config(state=tk.DISABLED)
        self.play_all_button.config(state=tk.DISABLED)
        self.stop_button.config(state=tk.NORMAL)

        # 在後台線程播放
        def play_thread():
            for i, seg in enumerate(segs, 1):
                if self.stop_flag:
                    break
                self.play_segment(speaker, seg, i, len(segs))
                time.sleep(0.3)  # 片段間隔

            self.root.after(0, lambda: self.on_play_done())

        thread = threading.Thread(target=play_thread, daemon=True)
        thread.start()

    def stop_playing(self):
        """停止播放"""
        self.stop_flag = True
        self.is_playing = False
        self.on_play_done()

    def on_play_done(self):
        """播放完成"""
        self.is_playing = False
        self.stop_flag = False
        self.play_button.config(state=tk.NORMAL)
        self.play_all_button.config(state=tk.NORMAL)
        self.stop_button.config(state=tk.DISABLED)
        self.progress_bar.config(value=0)
        self.progress_label.config(text="0:00 / 0:00")

        if self.stop_flag:
            self.status_label.config(text="⏹️ 已停止")
        else:
            self.status_label.config(text="✅ 播放完成")


def main():
    """主函數"""
    if not HAS_TKINTER:
        print("❌ tkinter 未安裝")
        print("請使用以下命令安裝:")
        print("  brew install python-tk@3.9")
        return

    root = tk.Tk()
    app = SpeakerPlayerGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()
