/**
 * 水平轨道时间线 — 片段 = 时间规划 + 类型标记，不绑定素材
 * 时间标尺(20px) + 水平片段卡片轨道(100x100) + HTML5拖拽排序
 * "+" 卡片 → 类型+时长选择器
 */
import React, {
  useState,
  useRef,
  useCallback,
  useEffect,
  useLayoutEffect,
} from "react";
import type { ClipData, ClipType } from "../types";

interface TimelinePanelProps {
  clips: ClipData[];
  selectedClipId: string | null;
  currentMode: string;
  onClipSelect: (clipId: string) => void;
  onClipReorder: (fromIdx: number, toIdx: number) => void;
  onClipRemove: (clipId: string) => void;
  onAddClip: (type: ClipType, duration: number) => void;
}

/** 片段类型图标 */
const CLIP_TYPE_ICONS: Record<ClipType, string> = {
  voice: "🎙️",
  pip: "🖼️",
};

/** 片段类型标签 */
const CLIP_TYPE_LABELS: Record<ClipType, string> = {
  voice: "口播",
  pip: "画中画",
};

const TimelinePanel: React.FC<TimelinePanelProps> = ({
  clips,
  selectedClipId,
  currentMode,
  onClipSelect,
  onClipReorder,
  onClipRemove,
  onAddClip,
}) => {
  const [dragIdx, setDragIdx] = useState<number | null>(null);
  const [dragOverIdx, setDragOverIdx] = useState<number | null>(null);
  const dragRef = useRef<number | null>(null);
  const [showAddPicker, setShowAddPicker] = useState(false);
  const pickerRef = useRef<HTMLDivElement>(null);
  const addCardRef = useRef<HTMLDivElement>(null);
  const [pickerPos, setPickerPos] = useState<{ top: number; right: number }>({
    top: 0,
    right: 0,
  });

  /* ── "+" 卡片：类型+时长选择状态 ── */
  const [addType, setAddType] = useState<ClipType>("voice");
  const [addDuration, setAddDuration] = useState<number>(5);

  /* ── 根据模式决定可选类型 ── */
  const availableTypes: ClipType[] =
    currentMode === "voice_over"
      ? ["voice"]
      : currentMode === "pip"
        ? ["pip"]
        : ["voice", "pip"]; // voice_pip 或默认

  /* ── 面板尺寸（宽度固定，高度由 useLayoutEffect 实测） ── */
  const PICKER_W = 240; // 面板宽度（与 CSS 一致）
  const GAP = 6; // 面板与"+"卡片的间距

  /* ── 计算 picker 初始位置（默认从"+"按钮上方弹出） ── */
  const updatePickerPosition = useCallback(() => {
    if (!addCardRef.current) return;
    const rect = addCardRef.current.getBoundingClientRect();
    const vw = window.innerWidth;

    /* 垂直方向：默认向上弹出（上方空间永远比下方大） */
    const roughHeight = 180; // 粗略估算，useLayoutEffect 会用实际高度校正
    let top = rect.top - GAP - roughHeight;
    if (top < 8) top = 8;

    /* 水平方向：右对齐"+"卡片；太靠右超出视口则左移 */
    let right = vw - rect.right;
    if (rect.right - PICKER_W < 8) {
      right = vw - PICKER_W - 8;
    }

    setPickerPos({ top, right });
  }, []);

  const handleTogglePicker = () => {
    if (!showAddPicker) {
      updatePickerPosition();
    }
    setShowAddPicker((v) => !v);
  };

  /* ── 渲染后用实际 offsetHeight 做精确边界校正（useLayoutEffect 确保 paint 前完成） ── */
  useLayoutEffect(() => {
    if (!showAddPicker || !pickerRef.current || !addCardRef.current) return;
    const pickerEl = pickerRef.current;
    const addRect = addCardRef.current.getBoundingClientRect();
    const pickerH = pickerEl.offsetHeight; // 实际高度，不用硬编码
    const vh = window.innerHeight;
    const vw = window.innerWidth;

    /* 默认：面板在"+"按钮上方 */
    let top = addRect.top - GAP - pickerH;

    /* 上方空间也不够（极端情况）→ 翻转到下方 */
    if (top < 8) {
      top = addRect.bottom + GAP;
      /* 下方也溢出 → clamp */
      if (top + pickerH > vh - 8) {
        top = vh - 8 - pickerH;
        if (top < 8) top = 8;
      }
    }

    /* 水平方向：右对齐"+"卡片；左侧溢出保护 */
    let right = vw - addRect.right;
    const pickerRect = pickerEl.getBoundingClientRect();
    if (pickerRect.left < 8) {
      right = vw - PICKER_W - 8;
    }

    setPickerPos({ top, right });
  }, [showAddPicker]);

  /* ── 点击外部关闭添加面板 ── */
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (pickerRef.current && !pickerRef.current.contains(e.target as Node)) {
        setShowAddPicker(false);
      }
    };
    if (showAddPicker) {
      document.addEventListener("mousedown", handleClickOutside);
    }
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [showAddPicker]);

  /* ── 确认添加片段 ── */
  const handleConfirmAdd = () => {
    onAddClip(addType, addDuration);
    setShowAddPicker(false);
  };

  /* ── 片段拖拽排序 ── */
  const handleDragStart = (e: React.DragEvent, idx: number) => {
    dragRef.current = idx;
    setDragIdx(idx);
    e.dataTransfer.setData("application/x-clip-drag", String(idx));
    e.dataTransfer.effectAllowed = "move";
  };

  const handleDragOver = (e: React.DragEvent, idx: number) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = "move";
    setDragOverIdx(idx);
  };

  const handleDragEnd = () => {
    dragRef.current = null;
    setDragIdx(null);
    setDragOverIdx(null);
  };

  const handleDrop = (e: React.DragEvent, toIdx: number) => {
    e.preventDefault();
    setDragOverIdx(null);
    const fromStr = e.dataTransfer.getData("application/x-clip-drag");
    if (fromStr !== "") {
      const fromIdx = Number(fromStr);
      if (fromIdx !== toIdx) {
        onClipReorder(fromIdx, toIdx);
      }
    }
  };

  /* ── 空轨道区域不接受素材拖入 ── */
  const handleEmptyDragOver = (e: React.DragEvent) => {
    e.preventDefault();
  };

  /* ── 时间标尺 ── */
  const totalDuration = clips.reduce((s, c) => s + c.duration, 0);
  const rulerMarks: number[] = [];
  const step = totalDuration <= 30 ? 5 : totalDuration <= 60 ? 10 : 15;
  for (let t = 0; t <= totalDuration + step; t += step) {
    rulerMarks.push(t);
  }

  const formatTime = (sec: number) => {
    const m = Math.floor(sec / 60);
    const s = Math.floor(sec % 60);
    return `${m}:${s.toString().padStart(2, "0")}`;
  };

  return (
    <div className="ep-timeline-area">
      {/* 时间线头部 */}
      <div className="ep-timeline-header">
        <div className="ep-timeline-title">
          <span>🎬 时间线</span>
          <span className="ep-timeline-duration">
            总时长: {formatTime(totalDuration)}
          </span>
        </div>
        <div className="ep-timeline-actions">
          <button
            className="ep-timeline-action-btn"
            onClick={() => {
              if (clips.length > 1) {
                const last = clips[clips.length - 1];
                onClipRemove(last.id);
              }
            }}
            title="删除最后一个片段"
          >
            ↩
          </button>
          <button className="ep-timeline-action-btn" title="重做">
            ↪
          </button>
        </div>
      </div>

      {/* 一镜到底提示 */}
      {currentMode === "one_take" && (
        <div className="ep-one-take-hint">🎥 一镜到底模式无片段</div>
      )}

      {/* 时间标尺 */}
      {currentMode !== "one_take" && (
        <div className="ep-time-ruler">
          <div
            className="ep-time-ruler-inner"
            style={{ width: Math.max(clips.length * 108, 300) }}
          >
            {rulerMarks.map((t) => (
              <span
                key={t}
                className="ep-time-mark"
                style={{
                  left:
                    totalDuration > 0
                      ? `${(t / totalDuration) * clips.length * 108}px`
                      : `${t * 20}px`,
                }}
              >
                {t}s
              </span>
            ))}
          </div>
        </div>
      )}

      {/* 水平片段轨道 */}
      {currentMode !== "one_take" && (
        <div className="ep-clip-track" onDragOver={handleEmptyDragOver}>
          {clips.length === 0 ? (
            <div className="ep-track-empty">
              <div className="ep-track-empty-icon">🎬</div>
              <div className="ep-track-empty-text">点击右侧 + 添加片段</div>
            </div>
          ) : (
            clips.map((clip, idx) => (
              <div
                key={clip.id}
                className={`ep-clip-card ${selectedClipId === clip.id ? "selected" : ""} ${dragIdx === idx ? "dragging" : ""} ${dragOverIdx === idx ? "drag-over" : ""}`}
                draggable
                onDragStart={(e) => handleDragStart(e, idx)}
                onDragOver={(e) => handleDragOver(e, idx)}
                onDragEnd={handleDragEnd}
                onDrop={(e) => handleDrop(e, idx)}
                onClick={() => onClipSelect(clip.id)}
              >
                {/* 类型图标 */}
                <div className="ep-clip-thumbnail">
                  {CLIP_TYPE_ICONS[clip.type] || "🎬"}
                </div>

                {/* 片段信息 */}
                <div className="ep-clip-info">
                  <span className="ep-clip-name">
                    {CLIP_TYPE_LABELS[clip.type] || "片段"} {idx + 1}
                  </span>
                  <span className="ep-clip-duration">{clip.duration}s</span>
                </div>

                {/* 删除按钮 */}
                <button
                  className="ep-clip-remove"
                  onClick={(e) => {
                    e.stopPropagation();
                    onClipRemove(clip.id);
                  }}
                >
                  ✕
                </button>
              </div>
            ))
          )}

          {/* ── 轨道末尾 "+" 添加卡片 → 类型+时长选择器 ── */}
          <div className="ep-track-add-card-wrapper">
            <div
              ref={addCardRef}
              className="ep-track-add-card"
              onClick={handleTogglePicker}
              title="添加片段"
            >
              +
            </div>
          </div>
        </div>
      )}

      {/* 类型+时长选择面板 — fixed 定位，不受任何父容器 overflow 裁剪 */}
      {showAddPicker && (
        <div
          ref={pickerRef}
          className="ep-add-clip-picker ep-add-clip-picker--portal"
          style={{
            position: "fixed",
            top: pickerPos.top,
            right: pickerPos.right,
          }}
        >
          <div className="ep-add-clip-picker-title">添加片段</div>

          {/* 类型选择 */}
          <div className="ep-add-clip-type-row">
            <span className="ep-add-clip-type-label">类型:</span>
            {availableTypes.map((t) => (
              <button
                key={t}
                className={`ep-add-clip-type-btn${addType === t ? " active" : ""}`}
                onClick={() => setAddType(t)}
              >
                {CLIP_TYPE_ICONS[t]} {CLIP_TYPE_LABELS[t]}
              </button>
            ))}
          </div>

          {/* 时长输入 */}
          <div className="ep-add-clip-duration-row">
            <span className="ep-add-clip-type-label">时长:</span>
            <input
              type="number"
              className="ep-duration-input"
              min={1}
              max={120}
              value={addDuration}
              onChange={(e) =>
                setAddDuration(
                  Math.max(1, Math.min(120, Number(e.target.value) || 1)),
                )
              }
            />
            <span className="ep-add-clip-duration-unit">秒</span>
          </div>

          {/* 确认按钮 */}
          <button
            className="ep-add-clip-confirm-btn"
            onClick={handleConfirmAdd}
          >
            添加
          </button>
        </div>
      )}
    </div>
  );
};

export default TimelinePanel;
