import { useCallback, useEffect, useRef, useState, type MouseEvent, type ReactNode } from "react";
import { Check, ChevronDown, Loader2, Mic, Pause, Play, Volume2 } from "lucide-react";
import { toast } from "sonner";
import { SelectPopover } from "@/shared/ui/SelectPopover";

interface VoiceOption {
  id: string;
  name: string;
}

const LOCALE_LABELS: Record<string, string> = {
  "zh-CN": "中文",
  "en-US": "English",
  "ja-JP": "日本語",
  "ko-KR": "한국어",
  "fr-FR": "Français",
  "de-DE": "Deutsch",
  "es-ES": "Español",
  "ru-RU": "Русский",
  "it-IT": "Italiano",
  "pt-BR": "Português",
};

const getLocaleFromVoiceId = (voiceId: string) => {
  const parts = voiceId.split("-");
  if (parts.length >= 2) {
    return `${parts[0]}-${parts[1]}`;
  }
  return voiceId;
};

interface VoiceSelectorProps {
  ttsMode: "edgetts" | "voiceclone";
  onSelectTtsMode: (mode: "edgetts" | "voiceclone") => void;
  voices: VoiceOption[];
  voice: string;
  onSelectVoice: (id: string) => void;
  voiceCloneSlot: ReactNode;
  embedded?: boolean;
}

export function VoiceSelector({
  ttsMode,
  onSelectTtsMode,
  voices,
  voice,
  onSelectVoice,
  voiceCloneSlot,
  embedded = false,
}: VoiceSelectorProps) {
  const selectedVoice = voices.find((v) => v.id === voice) ?? voices[0];
  const selectedLocale = selectedVoice ? getLocaleFromVoiceId(selectedVoice.id) : "";
  const selectedLangLabel = LOCALE_LABELS[selectedLocale] ?? selectedLocale;

  const [previewingVoiceId, setPreviewingVoiceId] = useState<string | null>(null);
  const [previewLoadingVoiceId, setPreviewLoadingVoiceId] = useState<string | null>(null);
  const previewPlayerRef = useRef<HTMLAudioElement | null>(null);
  const previewRequestIdRef = useRef(0);

  const stopVoicePreview = useCallback(() => {
    previewRequestIdRef.current += 1;

    if (previewPlayerRef.current) {
      previewPlayerRef.current.pause();
      previewPlayerRef.current.src = "";
      previewPlayerRef.current.currentTime = 0;
      previewPlayerRef.current = null;
    }
    setPreviewingVoiceId(null);
    setPreviewLoadingVoiceId(null);
  }, []);

  useEffect(() => () => {
    stopVoicePreview();
  }, [stopVoicePreview]);

  useEffect(() => {
    if (ttsMode !== "edgetts") {
      stopVoicePreview();
    }
  }, [ttsMode, stopVoicePreview]);

  const handleVoicePreview = useCallback(async (voiceId: string, e: MouseEvent<HTMLButtonElement>) => {
    e.stopPropagation();

    if (previewingVoiceId === voiceId) {
      stopVoicePreview();
      return;
    }

    stopVoicePreview();
    setPreviewLoadingVoiceId(voiceId);
    const requestId = ++previewRequestIdRef.current;

    try {
      const audioUrl = `/api/videos/voice-preview?voice=${encodeURIComponent(voiceId)}`;
      const player = new Audio(audioUrl);
      previewPlayerRef.current = player;
      let errorNotified = false;

      const notifyPreviewError = () => {
        if (errorNotified) return;
        errorNotified = true;
        toast.error("音色试听失败，请稍后重试");
      };

      player.onplaying = () => {
        if (requestId === previewRequestIdRef.current) {
          setPreviewLoadingVoiceId(null);
          setPreviewingVoiceId(voiceId);
        }
      };

      player.onended = () => {
        if (previewPlayerRef.current === player) {
          previewPlayerRef.current = null;
          setPreviewingVoiceId(null);
          setPreviewLoadingVoiceId(null);
        }
      };

      player.onerror = () => {
        if (previewPlayerRef.current === player) {
          previewPlayerRef.current = null;
          setPreviewingVoiceId(null);
          setPreviewLoadingVoiceId(null);
          notifyPreviewError();
        }
      };

      await player.play();

      if (requestId !== previewRequestIdRef.current) {
        player.pause();
        player.src = "";
        player.currentTime = 0;
      }
    } catch {
      toast.error("音色试听失败，请稍后重试");
    } finally {
      if (requestId === previewRequestIdRef.current) {
        setPreviewLoadingVoiceId(null);
      }
    }
  }, [previewingVoiceId, stopVoicePreview]);

  const content = (
    <>
      <div className="flex gap-2 mb-4">
        <button
          onClick={() => onSelectTtsMode("edgetts")}
          className={`flex-1 py-2 px-2 sm:px-4 rounded-lg text-sm sm:text-base font-medium transition-all flex items-center justify-center gap-1.5 sm:gap-2 ${ttsMode === "edgetts"
            ? "bg-purple-600 text-white"
            : "bg-white/10 text-gray-300 hover:bg-white/20"
            }`}
        >
          <Volume2 className="h-4 w-4 shrink-0" />
          选择声音
        </button>
        <button
          onClick={() => onSelectTtsMode("voiceclone")}
          className={`flex-1 py-2 px-2 sm:px-4 rounded-lg text-sm sm:text-base font-medium transition-all flex items-center justify-center gap-1.5 sm:gap-2 ${ttsMode === "voiceclone"
            ? "bg-purple-600 text-white"
            : "bg-white/10 text-gray-300 hover:bg-white/20"
            }`}
        >
          <Mic className="h-4 w-4 shrink-0" />
          克隆声音
        </button>
      </div>

      {ttsMode === "edgetts" && (
        <div className="space-y-2">
          <p className="text-xs text-gray-400">音色选择</p>
          <SelectPopover
            sheetTitle="选择声音"
            trigger={({ open, toggle }) => (
              <button
                type="button"
                onClick={toggle}
                className="w-full rounded-xl border border-white/10 bg-black/25 px-3 py-2.5 text-left hover:border-white/30 transition-colors"
              >
                <span className="flex items-center justify-between gap-3">
                  <span className="min-w-0">
                    <span className="block truncate text-sm text-white">
                      {selectedVoice?.name || "请选择声音"}
                    </span>
                    <span className="block text-xs text-gray-400">
                      {selectedLangLabel || "未识别语言"}
                    </span>
                  </span>
                  <ChevronDown className={`h-4 w-4 text-gray-300 transition-transform ${open ? "rotate-180" : ""}`} />
                </span>
              </button>
            )}
          >
            {({ close }) => (
              <div className="space-y-1">
                {voices.map((v) => {
                  const isSelected = voice === v.id;
                  const isPreviewing = previewingVoiceId === v.id;
                  const isPreviewLoading = previewLoadingVoiceId === v.id;
                  const locale = getLocaleFromVoiceId(v.id);
                  const langLabel = LOCALE_LABELS[locale] ?? locale;

                  return (
                    <div
                      key={v.id}
                      data-popover-selected={isSelected ? "true" : undefined}
                      className={`flex w-full items-center justify-between rounded-lg border px-3 py-2 text-left transition-colors ${isSelected
                        ? "border-purple-500 bg-purple-500/20"
                        : "border-white/10 bg-white/5 hover:border-white/30"
                        }`}
                    >
                      <button
                        type="button"
                        onClick={() => {
                          stopVoicePreview();
                          onSelectVoice(v.id);
                          close();
                        }}
                        className="min-w-0 flex-1 text-left"
                      >
                        <span className="block truncate text-sm text-white">{v.name}</span>
                        <span className="mt-0.5 block text-xs text-gray-400">{langLabel}</span>
                      </button>

                      <div className="flex items-center gap-2 pl-2">
                        <button
                          type="button"
                          onClick={(e) => {
                            void handleVoicePreview(v.id, e);
                          }}
                          className="p-1 text-gray-400 hover:text-purple-300 transition-colors"
                          title={isPreviewing ? "停止试听" : "试听"}
                        >
                          {isPreviewLoading ? (
                            <Loader2 className="h-4 w-4 animate-spin" />
                          ) : isPreviewing ? (
                            <Pause className="h-4 w-4" />
                          ) : (
                            <Play className="h-4 w-4" />
                          )}
                        </button>
                        {isSelected && <Check className="h-4 w-4 text-purple-300" />}
                      </div>
                    </div>
                  );
                })}
              </div>
            )}
          </SelectPopover>
        </div>
      )}

      {ttsMode === "voiceclone" && voiceCloneSlot}
    </>
  );

  if (embedded) return content;

  return (
    <div className="bg-white/5 rounded-2xl p-6 border border-white/10 backdrop-blur-sm">
      <h2 className="text-lg font-semibold text-white mb-4 flex items-center gap-2">
        🎙️ 配音方式
      </h2>
      {content}
    </div>
  );
}
