import { useCallback, useRef, useState, type CSSProperties, type MouseEvent as ReactMouseEvent, type TouchEvent as ReactTouchEvent } from "react";
import "../../styles/pages/dialog-generator.css";

type DialogStyle = "style1" | "style2" | "style3" | "style4";

interface DialogItem {
  id: number;
  style: DialogStyle;
  x: number;
  y: number;
  text: string;
  color: string;
  confirmed: boolean;
}

interface DragState {
  id: number;
  offsetX: number;
  offsetY: number;
}

const dialogStyles: Array<{
  key: DialogStyle;
  label: string;
  description: string;
  swatchClass: string;
}> = [
  { key: "style1", label: "白色圆角对话框", description: "适合浅色说明与标注", swatchClass: "is-white" },
  { key: "style2", label: "蓝色气泡对话框", description: "适合角色台词与重点提示", swatchClass: "is-blue" },
  { key: "style3", label: "黄色提示对话框", description: "适合醒目提醒与强调", swatchClass: "is-amber" },
  { key: "style4", label: "灰色简约对话框", description: "适合信息备注与辅助说明", swatchClass: "is-gray" },
];

const textColorOptions = [
  { value: "#ffffff", label: "白色" },
  { value: "#111827", label: "黑色" },
  { value: "#ef4444", label: "红色" },
  { value: "#f59e0b", label: "黄色" },
  { value: "#165dff", label: "蓝色" },
  { value: "#00ff88", label: "绿色" },
];

function DialogGeneratorPage() {
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const previewRef = useRef<HTMLDivElement | null>(null);
  const dragRef = useRef<DragState | null>(null);
  const nextIdRef = useRef(0);
  const [backgroundUrl, setBackgroundUrl] = useState("");
  const [dialogs, setDialogs] = useState<DialogItem[]>([]);
  const [selectedTextColor, setSelectedTextColor] = useState(textColorOptions[0].value);
  const [activeDragId, setActiveDragId] = useState<number | null>(null);

  const handleFile = useCallback((file?: File | null) => {
    if (!file || !file.type.startsWith("image/")) return;
    const reader = new FileReader();
    reader.onload = () => {
      if (typeof reader.result === "string") {
        setBackgroundUrl(reader.result);
      }
    };
    reader.readAsDataURL(file);
  }, []);

  const addDialog = useCallback((style: DialogStyle) => {
    nextIdRef.current += 1;
    const id = nextIdRef.current;
    setDialogs((current) => [
      ...current,
      {
        id,
        style,
        x: 30 + (id * 25) % 200,
        y: 30 + (id * 20) % 150,
        text: "",
        color: selectedTextColor,
        confirmed: false,
      },
    ]);
  }, [selectedTextColor]);

  const updateDialog = useCallback((id: number, patch: Partial<DialogItem>) => {
    setDialogs((current) => current.map((item) => (item.id === id ? { ...item, ...patch } : item)));
  }, []);

  const deleteDialog = useCallback((id: number) => {
    setDialogs((current) => current.filter((item) => item.id !== id));
  }, []);

  const startDrag = useCallback((id: number, clientX: number, clientY: number) => {
    const dialogEl = document.querySelector<HTMLElement>(`[data-dialog-id="${id}"]`);
    if (!dialogEl) return;
    const rect = dialogEl.getBoundingClientRect();
    dragRef.current = {
      id,
      offsetX: clientX - rect.left,
      offsetY: clientY - rect.top,
    };
    setActiveDragId(id);
  }, []);

  const moveDrag = useCallback((clientX: number, clientY: number) => {
    const drag = dragRef.current;
    const preview = previewRef.current;
    if (!drag || !preview) return;
    const dialogEl = document.querySelector<HTMLElement>(`[data-dialog-id="${drag.id}"]`);
    if (!dialogEl) return;

    const bounds = preview.getBoundingClientRect();
    const nextX = Math.max(0, Math.min(clientX - drag.offsetX - bounds.left, bounds.width - dialogEl.offsetWidth));
    const nextY = Math.max(0, Math.min(clientY - drag.offsetY - bounds.top, bounds.height - dialogEl.offsetHeight));
    updateDialog(drag.id, { x: nextX, y: nextY });
  }, [updateDialog]);

  const endDrag = useCallback(() => {
    dragRef.current = null;
    setActiveDragId(null);
  }, []);

  const handleCanvasMouseMove = useCallback((event: ReactMouseEvent<HTMLDivElement>) => {
    moveDrag(event.clientX, event.clientY);
  }, [moveDrag]);

  const handleCanvasTouchMove = useCallback((event: ReactTouchEvent<HTMLDivElement>) => {
    const touch = event.touches[0];
    if (!touch) return;
    moveDrag(touch.clientX, touch.clientY);
  }, [moveDrag]);

  return (
    <section className="dialog-generator-page page-motion">
      <div className="dialog-generator-shell">
        <aside className="dialog-generator-panel">
          <div className="dialog-generator-heading">
            <span className="dialog-generator-kicker">Interactive Dialog</span>
            <h1>交互式对话框生成器</h1>
            <p>上传背景图，在画面上添加可拖拽、可编辑的文字图层，用于图片标注、剧情分镜和互动内容设计。</p>
          </div>

          <div className="dialog-generator-section">
            <h2>上传背景图片</h2>
            <button
              type="button"
              className="dialog-generator-drop"
              onClick={() => fileInputRef.current?.click()}
              onDragOver={(event) => {
                event.preventDefault();
              }}
              onDrop={(event) => {
                event.preventDefault();
                handleFile(event.dataTransfer.files[0]);
              }}
            >
              <span className="dialog-generator-drop-icon">🖼</span>
              <strong>点击或拖拽图片到此处</strong>
              <small>支持 JPG、PNG、WEBP 格式</small>
            </button>
            <input
              ref={fileInputRef}
              type="file"
              accept="image/*"
              hidden
              onChange={(event) => handleFile(event.target.files?.[0])}
            />
          </div>

          <div className="dialog-generator-section">
            <h2>点击添加文字</h2>
            <p className="dialog-generator-hint">每点一次即在预览区新增一个可编辑文字图层。</p>
            <div className="dialog-generator-color-picker" role="radiogroup" aria-label="文字颜色">
              {textColorOptions.map((item) => (
                <button
                  key={item.value}
                  type="button"
                  className={`dialog-generator-color${selectedTextColor === item.value ? " is-active" : ""}`}
                  style={{ "--text-color": item.value } as CSSProperties}
                  aria-checked={selectedTextColor === item.value}
                  role="radio"
                  onClick={() => setSelectedTextColor(item.value)}
                >
                  <span />
                  <strong>{item.label}</strong>
                </button>
              ))}
            </div>
            <div className="dialog-generator-style-list">
              {dialogStyles.map((item) => (
                <button key={item.key} type="button" className="dialog-generator-style" onClick={() => addDialog(item.key)}>
                  <span className={`dialog-generator-swatch ${item.swatchClass}`} />
                  <span>
                    <strong>{item.label}</strong>
                    <small>{item.description}</small>
                  </span>
                </button>
              ))}
            </div>
          </div>

          <button type="button" className="dialog-generator-clear" onClick={() => setDialogs([])}>
            清空全部文字
          </button>
        </aside>

        <main className="dialog-generator-preview-card">
          <div className="dialog-generator-preview-head">
            <div>
              <span>Preview</span>
              <h2>预览区域</h2>
            </div>
            <p>拖动文字定位，输入文字后点击确认，确认后只保留文字图层，双击可重新编辑。</p>
          </div>

          <div
            ref={previewRef}
            className="dialog-generator-preview"
            onMouseMove={handleCanvasMouseMove}
            onMouseUp={endDrag}
            onMouseLeave={endDrag}
            onTouchMove={handleCanvasTouchMove}
            onTouchEnd={endDrag}
          >
            {backgroundUrl ? <div className="dialog-generator-image" style={{ backgroundImage: `url(${backgroundUrl})` }} /> : null}
            {!backgroundUrl ? (
              <div className="dialog-generator-empty">
                <span>🖼</span>
                <p>上传图片后开始编辑</p>
              </div>
            ) : null}

            {dialogs.map((dialog) => (
              <div
                key={dialog.id}
                data-dialog-id={dialog.id}
                className={`dialog-generator-bubble ${dialog.style}${dialog.confirmed ? " is-confirmed" : ""}${activeDragId === dialog.id ? " is-dragging" : ""}`}
                style={{ left: dialog.x, top: dialog.y, "--dialog-text-color": dialog.color } as CSSProperties}
                onMouseDown={(event) => {
                  const target = event.target as HTMLElement;
                  if (target.closest("textarea,button")) return;
                  startDrag(dialog.id, event.clientX, event.clientY);
                  event.preventDefault();
                }}
                onTouchStart={(event) => {
                  const target = event.target as HTMLElement;
                  if (target.closest("textarea,button")) return;
                  const touch = event.touches[0];
                  if (touch) startDrag(dialog.id, touch.clientX, touch.clientY);
                }}
                onDoubleClick={() => {
                  if (dialog.confirmed) updateDialog(dialog.id, { confirmed: false });
                }}
              >
                {!dialog.confirmed ? (
                  <button type="button" className="dialog-generator-delete" onClick={() => deleteDialog(dialog.id)} aria-label="删除文字">
                    ×
                  </button>
                ) : null}
                {dialog.confirmed ? (
                  <div className="dialog-generator-text-display">{dialog.text}</div>
                ) : (
                  <textarea
                    className="dialog-generator-text"
                    rows={2}
                    placeholder="输入文本..."
                    value={dialog.text}
                    onChange={(event) => updateDialog(dialog.id, { text: event.target.value })}
                  />
                )}
                {!dialog.confirmed ? (
                  <div className="dialog-generator-bubble-bottom">
                    <button
                      type="button"
                      className="dialog-generator-confirm"
                      onClick={() => {
                        if (dialog.text.trim()) {
                          updateDialog(dialog.id, { text: dialog.text.trim(), confirmed: true });
                        }
                      }}
                    >
                      ✓ 确认
                    </button>
                  </div>
                ) : null}
              </div>
            ))}
          </div>
        </main>
      </div>
    </section>
  );
}

export default DialogGeneratorPage;
