import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { ChangeEvent, MouseEvent } from "react";
import { Upload, RefreshCw, Play, Pause, Pencil, Trash2, Check, X, Mic, Square, RotateCw, Search, ChevronDown } from "lucide-react";
import { SelectPopover } from "@/shared/ui/SelectPopover";
import { AppModal, AppModalHeader } from "@/shared/ui/AppModal";

interface RefAudio {
  id: string;
  name: string;
  path: string;
  ref_text: string;
  duration_sec: number;
  created_at: number;
}

interface RefAudioPanelProps {
  refAudios: RefAudio[];
  selectedRefAudio: RefAudio | null;
  onSelectRefAudio: (audio: RefAudio) => void;
  isUploadingRef: boolean;
  uploadRefError: string | null;
  onClearUploadRefError: () => void;
  onUploadRefAudio: (file: File) => void;
  onFetchRefAudios: () => void;
  playingAudioId: string | null;
  onTogglePlayPreview: (audio: RefAudio, event: MouseEvent) => void;
  editingAudioId: string | null;
  editName: string;
  onEditNameChange: (value: string) => void;
  onStartEditing: (audio: RefAudio, event: MouseEvent) => void;
  onSaveEditing: (id: string, event: MouseEvent) => void;
  onCancelEditing: (event: MouseEvent) => void;
  onDeleteRefAudio: (id: string) => void;
  onRetranscribe: (id: string) => void;
  retranscribingId: string | null;
  recordedBlob: Blob | null;
  isRecording: boolean;
  recordingTime: number;
  onStartRecording: () => void;
  onStopRecording: () => void;
  onUseRecording: () => void | Promise<void>;
  onDiscardRecording: () => void;
  formatRecordingTime: (seconds: number) => string;
}

const OLD_FIXED_REF_TEXT = "其实生活中有许多美好的瞬间";

export function RefAudioPanel({
  refAudios,
  selectedRefAudio,
  onSelectRefAudio,
  isUploadingRef,
  uploadRefError,
  onClearUploadRefError,
  onUploadRefAudio,
  onFetchRefAudios,
  playingAudioId,
  onTogglePlayPreview,
  editingAudioId,
  editName,
  onEditNameChange,
  onStartEditing,
  onSaveEditing,
  onCancelEditing,
  onDeleteRefAudio,
  onRetranscribe,
  retranscribingId,
  recordedBlob,
  isRecording,
  recordingTime,
  onStartRecording,
  onStopRecording,
  onUseRecording,
  onDiscardRecording,
  formatRecordingTime,
}: RefAudioPanelProps) {
  const [recordedUrl, setRecordedUrl] = useState<string | null>(null);
  const [refAudioFilter, setRefAudioFilter] = useState("");
  const [recordingModalOpen, setRecordingModalOpen] = useState(false);
  const [recordedPreviewPlaying, setRecordedPreviewPlaying] = useState(false);
  const [recordedPreviewCurrentTime, setRecordedPreviewCurrentTime] = useState(0);
  const [recordedPreviewDuration, setRecordedPreviewDuration] = useState(0);
  const refAudioListContainerRef = useRef<HTMLDivElement | null>(null);
  const recordedAudioRef = useRef<HTMLAudioElement | null>(null);

  const stopRecordedPreview = useCallback(() => {
    const player = recordedAudioRef.current;
    if (!player) return;
    player.pause();
    player.currentTime = 0;
    setRecordedPreviewPlaying(false);
    setRecordedPreviewCurrentTime(0);
  }, []);

  useEffect(() => {
    if (!recordedBlob) {
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setRecordedUrl(null);
      return;
    }
    const url = URL.createObjectURL(recordedBlob);
    setRecordedUrl(url);
    return () => {
      URL.revokeObjectURL(url);
    };
  }, [recordedBlob]);

  const needsRetranscribe = (audio: RefAudio) =>
    audio.ref_text.startsWith(OLD_FIXED_REF_TEXT);

  const selectedRefAudioLabel = selectedRefAudio?.name || "请选择参考音频";
  const filteredRefAudios = useMemo(() => {
    const query = refAudioFilter.trim().toLowerCase();
    if (!query) return refAudios;
    return refAudios.filter((audio) => audio.name.toLowerCase().includes(query));
  }, [refAudioFilter, refAudios]);

  const handleOpenRefAudioPopover = useCallback(() => {
    setRefAudioFilter("");

    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        const container = refAudioListContainerRef.current;
        if (!container) return;
        const selectedRow = container.querySelector<HTMLElement>("[data-ref-selected='true']");
        selectedRow?.scrollIntoView({ block: "nearest", behavior: "auto" });
      });
    });
  }, []);

  const closeRecordingModal = () => {
    stopRecordedPreview();
    if (isRecording) {
      onStopRecording();
    }
    setRecordingModalOpen(false);
  };

  const handleUseRecordingAndClose = () => {
    stopRecordedPreview();
    setRecordingModalOpen(false);
    void onUseRecording();
  };

  const handleToggleRecordedPreview = () => {
    const player = recordedAudioRef.current;
    if (!player) return;

    if (player.paused) {
      player.play().catch(() => {
        setRecordedPreviewPlaying(false);
      });
      return;
    }

    player.pause();
  };

  const handleRecordedSeek = (event: ChangeEvent<HTMLInputElement>) => {
    const player = recordedAudioRef.current;
    if (!player) return;
    const nextTime = Number(event.target.value);
    player.currentTime = Number.isFinite(nextTime) ? nextTime : 0;
    setRecordedPreviewCurrentTime(Number.isFinite(nextTime) ? nextTime : 0);
  };

  const totalRecordedPreviewTime =
    Number.isFinite(recordedPreviewDuration) && recordedPreviewDuration > 0
      ? recordedPreviewDuration
      : recordingTime;

  return (
    <div className="space-y-4">
      <div>
        <div className="flex justify-between items-center mb-2">
          <span className="text-sm text-gray-300">📁 我的参考音频 <span className="text-xs text-gray-500 font-normal">(上传3-10秒语音样本)</span></span>
          <button
            onClick={onFetchRefAudios}
            className="px-2 py-1 text-xs bg-white/10 hover:bg-white/20 rounded text-gray-300 flex items-center gap-1"
          >
            <RefreshCw className="h-3.5 w-3.5" />
            刷新
          </button>
        </div>

        <input
          type="file"
          id="ref-audio-upload"
          accept=".wav,.mp3,.m4a,.webm,.ogg,.flac,.aac"
          onChange={(e) => {
            const file = e.target.files?.[0];
            if (file) {
              onUploadRefAudio(file);
            }
            e.target.value = "";
          }}
          className="hidden"
        />

        {isUploadingRef && (
          <div className="mb-2 p-2 bg-purple-500/10 rounded text-sm text-purple-300">
            ⏳ 上传并识别中...
          </div>
        )}

        {uploadRefError && (
          <div className="mb-2 p-2 bg-red-500/20 text-red-200 rounded text-xs flex justify-between">
            <span>❌ {uploadRefError}</span>
            <button onClick={onClearUploadRefError} className="text-red-300 hover:text-white">
              <X className="h-3.5 w-3.5" />
            </button>
          </div>
        )}

        {refAudios.length === 0 ? (
          <div className="text-center py-4 text-gray-500 text-sm">
            暂无参考音频，请上传或录制
          </div>
        ) : (
          <SelectPopover
            sheetTitle="选择参考音频"
            onOpen={handleOpenRefAudioPopover}
            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 transition-colors hover:border-white/30"
              >
                <span className="flex items-center justify-between gap-3">
                  <span className="min-w-0">
                    <span className="block text-xs text-gray-400">当前参考音频</span>
                    <span className="mt-0.5 block truncate text-sm text-white">{selectedRefAudioLabel}</span>
                  </span>
                  <ChevronDown className={`h-4 w-4 text-gray-300 transition-transform ${open ? "rotate-180" : ""}`} />
                </span>
              </button>
            )}
          >
            {({ close }) => (
              <div className="space-y-2">
                <div className="rounded-lg border border-white/10 bg-black/30 px-3 py-2">
                  <div className="flex items-center gap-2">
                    <Search className="h-4 w-4 text-gray-400" />
                    <input
                      type="text"
                      value={refAudioFilter}
                      onChange={(e) => setRefAudioFilter(e.target.value)}
                      placeholder="搜索参考音频..."
                      className="w-full bg-transparent text-sm text-white placeholder-gray-500 outline-none"
                    />
                  </div>
                </div>

                {filteredRefAudios.length === 0 ? (
                  <div className="py-6 text-center text-sm text-gray-400">没有匹配的参考音频</div>
                ) : (
                  <div ref={refAudioListContainerRef} className="space-y-1" style={{ contentVisibility: "auto" }}>
                    {filteredRefAudios.map((audio) => {
                      const isSelected = selectedRefAudio?.id === audio.id;

                      return (
                        <div
                          key={audio.id}
                          data-popover-selected={isSelected ? "true" : undefined}
                          data-ref-selected={isSelected ? "true" : "false"}
                          className={`flex items-center justify-between gap-2 rounded-lg border px-3 py-2 transition-colors ${isSelected
                            ? "border-purple-500 bg-purple-500/20"
                            : "border-white/10 bg-white/5 hover:border-white/30"
                            }`}
                        >
                          {editingAudioId === audio.id ? (
                            <div className="flex-1 flex items-center gap-2" onClick={(e) => e.stopPropagation()}>
                              <input
                                type="text"
                                value={editName}
                                onChange={(e) => onEditNameChange(e.target.value)}
                                className="w-full rounded border border-purple-500 bg-black/50 px-2 py-1 text-xs text-white focus:outline-none"
                                autoFocus
                                onKeyDown={(e) => {
                                  if (e.key === "Enter") onSaveEditing(audio.id, e as unknown as MouseEvent);
                                  if (e.key === "Escape") onCancelEditing(e as unknown as MouseEvent);
                                }}
                              />
                              <button type="button" onClick={(e) => onSaveEditing(audio.id, e)} className="text-green-400 hover:text-green-300">
                                <Check className="h-3.5 w-3.5" />
                              </button>
                              <button type="button" onClick={(e) => onCancelEditing(e)} className="text-gray-400 hover:text-gray-300">
                                <X className="h-3.5 w-3.5" />
                              </button>
                            </div>
                          ) : (
                            <button
                              type="button"
                              onClick={() => {
                                onSelectRefAudio(audio);
                                close();
                              }}
                              className="min-w-0 flex-1 text-left"
                            >
                              <span className="block truncate text-sm text-white" title={audio.name}>{audio.name}</span>
                              <span className="mt-0.5 block text-xs text-gray-400">
                                {audio.duration_sec.toFixed(1)}s
                                {needsRetranscribe(audio) && (
                                  <span className="ml-1 text-yellow-500" title="需要重新识别文字">⚠</span>
                                )}
                              </span>
                            </button>
                          )}

                          {editingAudioId !== audio.id && (
                            <div className="flex items-center gap-1 pl-2">
                              <button
                                type="button"
                                onClick={(e) => onTogglePlayPreview(audio, e)}
                                className="text-gray-400 hover:text-purple-300"
                                title="试听"
                              >
                                {playingAudioId === audio.id ? (
                                  <Pause className="h-3.5 w-3.5" />
                                ) : (
                                  <Play className="h-3.5 w-3.5" />
                                )}
                              </button>
                              <button
                                type="button"
                                onClick={(e) => {
                                  e.stopPropagation();
                                  onRetranscribe(audio.id);
                                }}
                                disabled={retranscribingId === audio.id}
                                className="text-gray-400 hover:text-cyan-400 disabled:opacity-50"
                                title="重新识别文字"
                              >
                                <RotateCw className={`h-3.5 w-3.5 ${retranscribingId === audio.id ? "animate-spin" : ""}`} />
                              </button>
                              <button
                                type="button"
                                onClick={(e) => onStartEditing(audio, e)}
                                className="text-gray-400 hover:text-blue-400"
                                title="重命名"
                              >
                                <Pencil className="h-3.5 w-3.5" />
                              </button>
                              <button
                                type="button"
                                onClick={(e) => {
                                  e.stopPropagation();
                                  onDeleteRefAudio(audio.id);
                                }}
                                className="text-gray-400 hover:text-red-400"
                                title="删除"
                              >
                                <Trash2 className="h-3.5 w-3.5" />
                              </button>
                              {isSelected && <Check className="h-3.5 w-3.5 text-purple-300" />}
                            </div>
                          )}
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
            )}
          </SelectPopover>
        )}

        <div className="mt-3 flex flex-wrap items-center justify-end gap-2">
          {recordedBlob && !isRecording && (
            <span className="mr-auto text-xs text-emerald-300/90">
              已录制 {formatRecordingTime(recordingTime)}，可点击“在线录音”处理
            </span>
          )}
          <label
            htmlFor="ref-audio-upload"
            className={`px-3 py-1.5 text-xs rounded-lg cursor-pointer transition-all inline-flex items-center gap-1.5 ${isUploadingRef
              ? "bg-gray-600 cursor-not-allowed text-gray-400 pointer-events-none"
              : "bg-purple-600 hover:bg-purple-700 text-white"
              }`}
          >
            <Upload className="h-3.5 w-3.5" />
            上传音频
          </label>
          <button
            type="button"
            onClick={() => setRecordingModalOpen(true)}
            disabled={isUploadingRef}
            className="px-3 py-1.5 text-xs rounded-lg transition-colors bg-red-600 hover:bg-red-700 text-white disabled:bg-gray-600 disabled:text-gray-400 inline-flex items-center gap-1.5"
          >
            <Mic className="h-3.5 w-3.5" />
            在线录音
          </button>
        </div>
      </div>

      {recordingModalOpen && (
        <AppModal
          isOpen={recordingModalOpen}
          onClose={closeRecordingModal}
          panelClassName="w-full max-w-lg rounded-2xl border border-white/10 bg-[#171821]/95 shadow-[0_24px_80px_rgba(0,0,0,0.55)] overflow-hidden"
          closeOnOverlay={false}
        >
          <AppModalHeader
            title="🎤 在线录音"
            subtitle="建议录制 3-10 秒，超出会自动截取到可用长度"
            onClose={closeRecordingModal}
          />

          <div className="space-y-4 p-4 sm:p-5">
            <div className="rounded-xl border border-white/10 bg-black/25 p-3 sm:p-4">
              <div className="flex flex-wrap items-center gap-2">
                {!isRecording ? (
                  <button
                    type="button"
                    onClick={onStartRecording}
                    disabled={isUploadingRef}
                    className="px-4 py-2 rounded-lg text-sm font-medium bg-red-600 hover:bg-red-700 text-white transition-colors disabled:bg-gray-600 disabled:text-gray-400 inline-flex items-center gap-2"
                  >
                    <Mic className="h-4 w-4" />
                    {recordedBlob ? "重新录音" : "开始录音"}
                  </button>
                ) : (
                  <button
                    type="button"
                    onClick={onStopRecording}
                    className="px-4 py-2 rounded-lg text-sm font-medium bg-gray-600 hover:bg-gray-700 text-white transition-colors inline-flex items-center gap-2"
                  >
                    <Square className="h-4 w-4" />
                    停止录音
                  </button>
                )}

                {isRecording ? (
                  <span className="inline-flex items-center gap-1 rounded-full border border-red-400/40 bg-red-500/10 px-3 py-1 text-xs text-red-300 animate-pulse">
                    <span className="h-1.5 w-1.5 rounded-full bg-red-400" />
                    录音中 {formatRecordingTime(recordingTime)}
                  </span>
                ) : recordedBlob ? (
                  <span className="inline-flex items-center gap-1 rounded-full border border-emerald-400/30 bg-emerald-500/10 px-3 py-1 text-xs text-emerald-300">
                    已录制 {formatRecordingTime(recordingTime)}
                  </span>
                ) : null}
              </div>

              {!recordedBlob && !isRecording && (
                <p className="mt-3 text-xs text-gray-500">点击“开始录音”后允许麦克风权限，结束后可试听并确认上传</p>
              )}
            </div>

            {recordedBlob && !isRecording && (
              <div className="space-y-3 rounded-xl border border-emerald-500/30 bg-emerald-500/10 p-3">
                <div className="flex items-center justify-between gap-2">
                  <span className="text-sm text-emerald-200">✅ 录音完成，可先试听再使用</span>
                  <span className="text-xs text-emerald-300/80">{formatRecordingTime(recordingTime)}</span>
                </div>

                <div className="rounded-lg border border-white/10 bg-black/35 px-3 py-2.5">
                  <audio
                    key={recordedUrl || "recorded-preview"}
                    ref={recordedAudioRef}
                    src={recordedUrl || ""}
                    className="hidden"
                    onPlay={() => setRecordedPreviewPlaying(true)}
                    onPause={() => setRecordedPreviewPlaying(false)}
                    onEnded={() => {
                      setRecordedPreviewPlaying(false);
                      setRecordedPreviewCurrentTime(0);
                    }}
                    onTimeUpdate={(event) => setRecordedPreviewCurrentTime(event.currentTarget.currentTime || 0)}
                    onLoadedMetadata={(event) => setRecordedPreviewDuration(event.currentTarget.duration || 0)}
                  />

                  <div className="flex items-center gap-3">
                    <button
                      type="button"
                      onClick={handleToggleRecordedPreview}
                      disabled={!recordedUrl}
                      className="h-8 w-8 shrink-0 rounded-full bg-white/10 hover:bg-white/20 text-emerald-200 disabled:text-gray-500 disabled:bg-white/5 inline-flex items-center justify-center transition-colors"
                      title={recordedPreviewPlaying ? "暂停试听" : "播放试听"}
                    >
                      {recordedPreviewPlaying ? (
                        <Pause className="h-4 w-4" />
                      ) : (
                        <Play className="h-4 w-4 translate-x-[1px]" />
                      )}
                    </button>

                    <div className="min-w-0 flex-1">
                      <input
                        type="range"
                        min={0}
                        max={Math.max(totalRecordedPreviewTime, 0.1)}
                        step={0.01}
                        value={Math.min(recordedPreviewCurrentTime, totalRecordedPreviewTime || 0)}
                        onChange={handleRecordedSeek}
                        className="w-full h-1.5 cursor-pointer appearance-none rounded-full bg-white/15 accent-emerald-400"
                      />
                      <div className="mt-1 flex items-center justify-between text-[11px] text-emerald-200/80">
                        <span>{formatRecordingTime(Math.floor(recordedPreviewCurrentTime))}</span>
                        <span>{formatRecordingTime(Math.floor(totalRecordedPreviewTime))}</span>
                      </div>
                    </div>
                  </div>
                </div>

                <div className="flex flex-wrap items-center justify-end gap-2">
                  <button
                    type="button"
                    onClick={onDiscardRecording}
                    disabled={isUploadingRef}
                    className="px-3 py-1.5 rounded-lg text-sm bg-white/10 hover:bg-white/20 text-gray-200 transition-colors disabled:bg-white/5 disabled:text-gray-500"
                  >
                    弃用本次录音
                  </button>
                  <button
                    type="button"
                    onClick={handleUseRecordingAndClose}
                    disabled={isUploadingRef}
                    className="px-3 py-1.5 rounded-lg text-sm bg-green-600 hover:bg-green-700 text-white transition-colors disabled:bg-gray-600 disabled:text-gray-400"
                  >
                    使用此录音
                  </button>
                </div>
              </div>
            )}
          </div>
        </AppModal>
      )}

    </div>
  );
}
