import { useEffect, useMemo, useRef, useState } from "react";
import { convertFileSrc, invoke } from "@tauri-apps/api/core";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { Check, MousePointer2, Trash2, X } from "lucide-react";
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../components/ui/select";

const regionTypes = [
  { value: "contact_list", label: "联系人区域" },
  { value: "chat_content", label: "聊天内容区域" },
  { value: "input_box", label: "输入框区域" },
  { value: "send_button", label: "发送按钮区域" },
  { value: "custom", label: "自定义区域" },
];

const emptyCapture = {
  screenshotPath: "",
  screenshotWidth: 0,
  screenshotHeight: 0,
  scaleFactor: window.devicePixelRatio || 1,
};

function clamp(value, min, max) {
  return Math.min(Math.max(value, min), max);
}

function normalizeBox(start, end) {
  return [
    Math.min(start.x, end.x),
    Math.min(start.y, end.y),
    Math.max(start.x, end.x),
    Math.max(start.y, end.y),
  ];
}

function roundCoord(value) {
  return Math.round(value * 100) / 100;
}

function toScreenBox(box, capture) {
  const scaleFactor = capture.scaleFactor || 1;
  const sourceX = capture.source?.x || 0;
  const sourceY = capture.source?.y || 0;
  const sourceBox = toSourceBox(box, scaleFactor);

  return [
    roundCoord(sourceX + sourceBox[0]),
    roundCoord(sourceY + sourceBox[1]),
    roundCoord(sourceX + sourceBox[2]),
    roundCoord(sourceY + sourceBox[3]),
  ];
}

function toSourceBox(box, scaleFactor) {
  return box.map((value) => roundCoord(value / scaleFactor));
}

function createRegion(box, capture) {
  const bboxImage = box.map(roundCoord);
  const type = "custom";

  return {
    id: crypto.randomUUID(),
    name: `区域 ${new Date().toLocaleTimeString("zh-CN", { hour12: false })}`,
    type,
    description: "",
    bbox_image: bboxImage,
    bbox_source: toSourceBox(bboxImage, capture.scaleFactor || 1),
    bbox_screen: toScreenBox(bboxImage, capture),
    scaleFactor: capture.scaleFactor || 1,
  };
}

function normalizeRegion(region) {
  return {
    ...region,
    description: region.description || "",
    bbox_source: region.bbox_source || region.bbox_image.map((value) => roundCoord(value / (region.scaleFactor || 1))),
  };
}

function formatCaptureTiming(capture, frontendMs) {
  const totalMs = capture.totalMs ?? Math.round(frontendMs);

  return [
    "拖拽截图区域创建矩形框",
    `总耗时 ${totalMs}ms`,
    `枚举屏幕 ${capture.screenListMs ?? "-"}ms`,
    `截屏 ${capture.captureMs ?? "-"}ms`,
    `保存 ${capture.saveMs ?? "-"}ms`,
    `前端等待 ${Math.round(frontendMs)}ms`,
  ].join(" · ");
}

export default function AnnotationPage() {
  const [capture, setCapture] = useState(emptyCapture);
  const [regions, setRegions] = useState([]);
  const [selectedId, setSelectedId] = useState(null);
  const [drawStart, setDrawStart] = useState(null);
  const [drawEnd, setDrawEnd] = useState(null);
  const [status, setStatus] = useState("正在准备截图...");
  const [saving, setSaving] = useState(false);
  const imageRef = useRef(null);

  const selectedRegion = regions.find((region) => region.id === selectedId) || null;
  const screenshotSrc = capture.screenshotPath ? convertFileSrc(capture.screenshotPath) : "";
  const tempBox = drawStart && drawEnd ? normalizeBox(drawStart, drawEnd) : null;

  const typeLabelMap = useMemo(
    () => Object.fromEntries(regionTypes.map((type) => [type.value, type.label])),
    [],
  );

  useEffect(() => {
    let cancelled = false;

    async function init() {
      const stored = sessionStorage.getItem("pendingAnnotationCapture");
      if (stored) {
        const nextCapture = JSON.parse(stored);
        if (!cancelled) {
          setCapture(nextCapture);
          setStatus("拖拽截图区域创建矩形框");
          if (window.__TAURI_INTERNALS__) {
            await getCurrentWindow().setFullscreen(true);
          }
        }
        return;
      }

      const sharedCapture = localStorage.getItem("annotationCaptureResult");
      if (sharedCapture) {
        const nextCapture = JSON.parse(sharedCapture);
        if (!cancelled) {
          setCapture(nextCapture);
          setStatus("拖拽截图区域创建矩形框");
        }
        return;
      }

      if (localStorage.getItem("annotationCaptureStatus") === "pending") {
        setStatus("正在截取屏幕，请稍候...");
        const startedAt = performance.now();
        const nextCapture = await new Promise((resolve, reject) => {
          const readResult = () => {
            const result = localStorage.getItem("annotationCaptureResult");
            if (result) {
              resolve(JSON.parse(result));
              return true;
            }

            const error = localStorage.getItem("annotationCaptureError");
            if (error) {
              reject(new Error(error));
              return true;
            }

            return false;
          };

          if (readResult()) return;

          const timer = window.setInterval(() => {
            if (readResult()) window.clearInterval(timer);
          }, 100);

          window.addEventListener("storage", () => readResult(), { once: true });
        });

        if (!cancelled) {
          sessionStorage.setItem("pendingAnnotationCapture", JSON.stringify(nextCapture));
          setCapture(nextCapture);
          setStatus(formatCaptureTiming(nextCapture, performance.now() - startedAt));
        }
        return;
      }

      if (!window.__TAURI_INTERNALS__) {
        setStatus("浏览器预览模式无法截屏，请在 Tauri 应用中使用");
        return;
      }

      setStatus("正在截取屏幕，请稍候...");
      const startedAt = performance.now();
      const nextCapture = await invoke("capture_screen");
      if (!cancelled) {
        sessionStorage.setItem("pendingAnnotationCapture", JSON.stringify(nextCapture));
        setCapture(nextCapture);
        setStatus(formatCaptureTiming(nextCapture, performance.now() - startedAt));
        await getCurrentWindow().setFullscreen(true);
      }
    }

    init().catch((error) => {
      setStatus(`截屏失败：${String(error)}`);
    });

    return () => {
      cancelled = true;
    };
  }, []);

  useEffect(() => {
    async function loadSaved() {
      if (!window.__TAURI_INTERNALS__) return;

      const saved = await invoke("load_regions");
      if (saved?.regions?.length) {
        setRegions(saved.regions.map(normalizeRegion));
        setSelectedId(saved.regions[0].id);
      }
    }

    loadSaved().catch(() => {});
  }, []);

  function getImagePoint(event) {
    const rect = imageRef.current?.getBoundingClientRect();
    if (!rect || !capture.screenshotWidth || !capture.screenshotHeight) return null;

    const displayX = clamp(event.clientX - rect.left, 0, rect.width);
    const displayY = clamp(event.clientY - rect.top, 0, rect.height);

    return {
      x: (displayX * capture.screenshotWidth) / rect.width,
      y: (displayY * capture.screenshotHeight) / rect.height,
    };
  }

  function handlePointerDown(event) {
    if (event.button !== 0) return;
    const point = getImagePoint(event);
    if (!point) return;

    event.currentTarget.setPointerCapture(event.pointerId);
    setDrawStart(point);
    setDrawEnd(point);
    setSelectedId(null);
  }

  function handlePointerMove(event) {
    if (!drawStart) return;
    const point = getImagePoint(event);
    if (point) setDrawEnd(point);
  }

  function handlePointerUp(event) {
    if (!drawStart || !drawEnd) return;

    if (event.currentTarget.hasPointerCapture(event.pointerId)) {
      event.currentTarget.releasePointerCapture(event.pointerId);
    }

    const box = normalizeBox(drawStart, drawEnd);
    const width = box[2] - box[0];
    const height = box[3] - box[1];
    setDrawStart(null);
    setDrawEnd(null);

    if (width < 6 || height < 6) return;

    const region = createRegion(box, capture);
    setRegions((current) => [...current, region]);
    setSelectedId(region.id);
  }

  function handlePointerCancel(event) {
    if (event.currentTarget.hasPointerCapture(event.pointerId)) {
      event.currentTarget.releasePointerCapture(event.pointerId);
    }
    setDrawStart(null);
    setDrawEnd(null);
  }

  function updateSelected(patch) {
    setRegions((current) =>
      current.map((region) => (region.id === selectedId ? { ...region, ...patch } : region)),
    );
  }

  function deleteSelected() {
    if (!selectedId) return;
    setRegions((current) => current.filter((region) => region.id !== selectedId));
    setSelectedId(null);
  }

  async function exitAnnotation() {
    sessionStorage.removeItem("pendingAnnotationCapture");
    localStorage.removeItem("annotationCaptureStatus");
    localStorage.removeItem("annotationCaptureResult");
    localStorage.removeItem("annotationCaptureError");
    localStorage.removeItem("annotationCaptureSource");
    if (window.__TAURI_INTERNALS__) {
      const currentWindow = getCurrentWindow();
      if (currentWindow.label !== "main") {
        await currentWindow.close();
        return;
      }

      await currentWindow.setFullscreen(false);
    }
    window.location.hash = "/";
  }

  async function save() {
    if (!window.__TAURI_INTERNALS__) {
      setStatus("浏览器预览模式无法保存到本地文件");
      return;
    }

    setSaving(true);
    const now = new Date().toISOString();
    const existing = await invoke("load_regions").catch(() => null);
    const annotation = {
      app: "wechat",
      screenshotPath: capture.screenshotPath,
      screenshotWidth: capture.screenshotWidth,
      screenshotHeight: capture.screenshotHeight,
      scaleFactor: capture.scaleFactor || 1,
      source: capture.source || null,
      regions,
      createdAt: existing?.createdAt || now,
      updatedAt: now,
    };

    try {
      const path = await invoke("save_regions", { annotation });
      sessionStorage.setItem("lastRegionsPath", path);
      setStatus(`已保存：${path}`);
      await exitAnnotation();
    } catch (error) {
      setStatus(`保存失败：${String(error)}`);
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="flex h-dvh w-full overflow-hidden bg-page text-text">
      <aside className="flex w-[320px] shrink-0 flex-col border-r border-line bg-surface p-4 shadow-2xl" onPointerDown={(event) => event.stopPropagation()}>
        <div>
          <div className="flex items-center gap-2 text-[13px] font-black text-primary">
            <MousePointer2 size={16} />
            屏幕区域标注
          </div>
          <h1 className="mt-2 text-[20px] font-extrabold">微信 RPA 坐标配置</h1>
          <p className="mt-2 text-[12px] leading-5 text-muted">{status}</p>
        </div>

        <div className="mt-4 grid grid-cols-2 gap-2 rounded-[12px] border border-line bg-surface2 p-3 text-[11px] text-muted">
          <span>截图像素</span>
          <span className="text-right text-text">{capture.screenshotWidth} x {capture.screenshotHeight}</span>
          <span>ScaleFactor</span>
          <span className="text-right text-text">{capture.scaleFactor || 1}</span>
          <span>区域数量</span>
          <span className="text-right text-text">{regions.length}</span>
          <span>来源</span>
          <span className="truncate text-right text-text">{capture.source?.kind === "window" ? "窗口" : "桌面"}</span>
        </div>

        <div className="mt-4 space-y-3 rounded-[14px] border border-line bg-surface2 p-3">
          <label className="block text-[12px] font-bold text-muted">区域名称</label>
          <input
            className="input-like"
            value={selectedRegion?.name || ""}
            onChange={(event) => updateSelected({ name: event.target.value })}
            disabled={!selectedRegion}
            placeholder="先拖拽创建一个区域"
          />

          <label className="block text-[12px] font-bold text-muted">区域类型</label>
          <Select
            value={selectedRegion?.type || "custom"}
            onValueChange={(value) => updateSelected({ type: value })}
            disabled={!selectedRegion}
          >
            <SelectTrigger>
              <SelectValue placeholder="选择区域类型" />
            </SelectTrigger>
            <SelectContent>
              <SelectGroup>
                {regionTypes.map((type) => (
                  <SelectItem key={type.value} value={type.value}>{type.label}</SelectItem>
                ))}
              </SelectGroup>
            </SelectContent>
          </Select>

          <label className="block text-[12px] font-bold text-muted">区域用途描述</label>
          <textarea
            className="editor min-h-[84px]"
            value={selectedRegion?.description || ""}
            onChange={(event) => updateSelected({ description: event.target.value })}
            disabled={!selectedRegion}
            placeholder="例如：这是微信聊天消息列表，用于识别最近一条用户消息；这是发送按钮，用于点击发送。自定义区域请尽量描述它的用途和可执行动作。"
          />

          {selectedRegion ? (
            <div className="rounded-[10px] bg-page p-2 font-mono text-[11px] leading-5 text-muted">
              <div>image: [{selectedRegion.bbox_image.join(", ")}]</div>
              <div>screen: [{selectedRegion.bbox_screen.join(", ")}]</div>
            </div>
          ) : null}

          <button className="btn-danger h-9 w-full gap-2" onClick={deleteSelected} disabled={!selectedRegion}>
            <Trash2 size={15} />
            删除当前框
          </button>
        </div>

        <div className="mt-4 min-h-0 flex-1 overflow-y-auto pr-1">
          <div className="mb-2 text-[12px] font-black text-muted">区域列表</div>
          <div className="space-y-2">
            {regions.map((region, index) => (
              <button
                key={region.id}
                className={`w-full rounded-[12px] border p-3 text-left transition ${
                  region.id === selectedId
                    ? "border-primary bg-primary/15"
                    : "border-line bg-surface hover:bg-surface2"
                }`}
                onClick={() => setSelectedId(region.id)}
              >
                <div className="flex items-center justify-between gap-2">
                  <span className="text-[13px] font-extrabold">{index + 1}. {region.name}</span>
                  <span className="rounded-full border border-line bg-surface2 px-2 py-0.5 text-[10px] text-muted">{typeLabelMap[region.type]}</span>
                </div>
                {region.description ? (
                  <div className="mt-1 line-clamp-2 text-[11px] leading-4 text-muted">{region.description}</div>
                ) : null}
                <div className="mt-1 font-mono text-[10px] text-subtle">[{region.bbox_screen.join(", ")}]</div>
              </button>
            ))}
          </div>
        </div>

        <div className="mt-4 grid grid-cols-2 gap-3">
          <button className="btn-secondary h-10 gap-2" onClick={exitAnnotation}>
            <X size={16} />
            取消
          </button>
          <button className="btn-primary h-10 gap-2" onClick={save} disabled={saving || !capture.screenshotPath}>
            <Check size={16} />
            {saving ? "保存中" : "保存"}
          </button>
        </div>
      </aside>

      <main className="flex min-w-0 flex-1 items-center justify-center overflow-auto bg-surface2 p-6">
        <div className="relative max-h-full max-w-full select-none shadow-[0_20px_80px_rgba(0,0,0,.55)]">
          {screenshotSrc ? (
            <>
              <img
                ref={imageRef}
                src={screenshotSrc}
                alt="当前屏幕截图"
                className="block max-h-[calc(100dvh-48px)] max-w-full object-contain"
                draggable={false}
                onLoad={() => setStatus("拖拽截图区域创建矩形框")}
                onError={() => setStatus(`截图图片加载失败：${capture.screenshotPath}`)}
              />
              <svg
                className="absolute inset-0 h-full w-full touch-none"
                viewBox={`0 0 ${capture.screenshotWidth} ${capture.screenshotHeight}`}
                preserveAspectRatio="none"
                onPointerDown={handlePointerDown}
                onPointerMove={handlePointerMove}
                onPointerUp={handlePointerUp}
                onPointerCancel={handlePointerCancel}
              >
                <rect width={capture.screenshotWidth} height={capture.screenshotHeight} fill="transparent" />
                {regions.map((region) => {
                  const [x1, y1, x2, y2] = region.bbox_image;
                  const selected = region.id === selectedId;
                  return (
                    <g key={region.id} onPointerDown={(event) => { event.stopPropagation(); setSelectedId(region.id); }}>
                      <rect
                        x={x1}
                        y={y1}
                        width={x2 - x1}
                        height={y2 - y1}
                        fill={selected ? "rgba(7,193,96,0.28)" : "rgba(45,140,255,0.18)"}
                        stroke={selected ? "#07c160" : "#2d8cff"}
                        strokeWidth={selected ? 5 : 3}
                        vectorEffect="non-scaling-stroke"
                      />
                      <text
                        x={x1 + 8}
                        y={Math.max(y1 + 24, 24)}
                        fill="#fff"
                        stroke="rgba(0,0,0,.7)"
                        strokeWidth="4"
                        paintOrder="stroke"
                        fontSize="18"
                        fontWeight="800"
                      >
                        {region.name}
                      </text>
                    </g>
                  );
                })}
                {tempBox ? (
                  <rect
                    x={tempBox[0]}
                    y={tempBox[1]}
                    width={tempBox[2] - tempBox[0]}
                    height={tempBox[3] - tempBox[1]}
                    fill="rgba(7,193,96,0.2)"
                    stroke="#07c160"
                    strokeDasharray="10 8"
                    strokeWidth="4"
                    vectorEffect="non-scaling-stroke"
                  />
                ) : null}
              </svg>
            </>
          ) : (
            <div className="grid h-[360px] w-[640px] place-items-center rounded-[20px] border border-line bg-surface text-muted">
              {status}
            </div>
          )}
        </div>
      </main>
    </div>
  );
}
