import { useEffect, useMemo, useRef, useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { Bot, SendHorizontal, UserRound } from "lucide-react";

const MONITOR_ENDPOINT = "http://127.0.0.1:8765";

function messageLabel(role) {
  if (role === "me") return "我";
  if (role === "user") return "客户";
  return "未知";
}

export default function EngineWorkbench() {
  const [monitorEvent, setMonitorEvent] = useState(null);
  const [streamUrl, setStreamUrl] = useState(`${MONITOR_ENDPOINT}/frame.jpg?t=${Date.now()}`);
  const [streamFps, setStreamFps] = useState(0);
  const [streamError, setStreamError] = useState("");
  const [annotation, setAnnotation] = useState(null);
  const [frameMeta, setFrameMeta] = useState(null);
  const [videoBox, setVideoBox] = useState({ width: 0, height: 0 });
  const [question, setQuestion] = useState("");
  const [qaMessages, setQaMessages] = useState([]);
  const sequenceRef = useRef({ sequence: null, time: 0 });
  const streamRefreshedRef = useRef(false);

  useEffect(() => {
    if (!window.__TAURI_INTERNALS__) return;
    invoke("start_vision_stream").catch((error) => {
      setStreamError(`预览服务启动失败：${String(error)}`);
    });
    invoke("load_regions")
      .then((saved) => setAnnotation(saved || null))
      .catch(() => setAnnotation(null));
  }, []);

  useEffect(() => {
    const updateBox = () => {
      const element = document.getElementById("wechat-preview-frame");
      if (!element) return;
      const rect = element.getBoundingClientRect();
      setVideoBox({ width: rect.width, height: rect.height });
    };
    updateBox();
    window.addEventListener("resize", updateBox);
    return () => window.removeEventListener("resize", updateBox);
  }, []);

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

    async function pollMonitor() {
      try {
        const response = await fetch(`${MONITOR_ENDPOINT}/latest.json?t=${Date.now()}`, { cache: "no-store" });
        const data = await response.json();
        if (!cancelled) {
          if (data.source !== "go-window-capture") {
            setMonitorEvent(null);
            setStreamFps(0);
            setStreamError(`预览服务来源异常：${data.source || "unknown"}`);
            return;
          }
          if (data.event?.type === "source_waiting") {
            setMonitorEvent(null);
            setStreamFps(0);
            setStreamError(data.event.message || "等待标注来源窗口出现...");
            setFrameMeta(data.frame || null);
            return;
          }
          setStreamError("");
          setFrameMeta(data.frame || null);
          const now = performance.now();
          const previous = sequenceRef.current;
          if (typeof data.sequence === "number" && typeof previous.sequence === "number" && previous.time) {
            const elapsedSeconds = Math.max((now - previous.time) / 1000, 0.001);
            setStreamFps(Math.max(0, (data.sequence - previous.sequence) / elapsedSeconds));
          }
          sequenceRef.current = { sequence: data.sequence, time: now };
          setMonitorEvent(data.event?.type === "preview_frame" ? data.event : null);
          if (typeof data.sequence === "number" && data.sequence > 0) {
            streamRefreshedRef.current = true;
            setStreamUrl(`${MONITOR_ENDPOINT}/frame.jpg?seq=${data.sequence}&t=${Date.now()}`);
          }
        }
      } catch {
        if (!cancelled) {
          setMonitorEvent(null);
          setStreamError("等待预览服务启动...");
        }
      }
    }

    pollMonitor();
    const timer = window.setInterval(pollMonitor, 500);
    return () => {
      cancelled = true;
      window.clearInterval(timer);
    };
  }, []);

  const latestLlm = monitorEvent?.latest_llm || monitorEvent?.llm_chat_reading || null;
  const visibleMessages = useMemo(() => latestLlm?.visible_messages || [], [latestLlm]);
  const latestUserMessage = latestLlm?.latest_user_message || "等待识别当前聊天记录";
  const replyText = latestLlm?.reply_text || "暂无建议回复";
  const overlay = useMemo(() => {
    const frameWidth = frameMeta?.width || annotation?.screenshotWidth;
    const frameHeight = frameMeta?.height || annotation?.screenshotHeight;
    if (!frameWidth || !frameHeight || !videoBox.width || !videoBox.height) return null;
    const scale = Math.min(videoBox.width / frameWidth, videoBox.height / frameHeight);
    const width = frameWidth * scale;
    const height = frameHeight * scale;
    return {
      left: (videoBox.width - width) / 2,
      top: (videoBox.height - height) / 2,
      scale,
      frameWidth,
      frameHeight,
    };
  }, [annotation, frameMeta, videoBox]);

  function regionStyle(region) {
    if (!overlay || !region.bbox_image) return null;
    const sourceWidth = annotation?.screenshotWidth || overlay.frameWidth;
    const sourceHeight = annotation?.screenshotHeight || overlay.frameHeight;
    const [ix1, iy1, ix2, iy2] = region.bbox_image;
    const x1 = (ix1 * overlay.frameWidth) / sourceWidth;
    const y1 = (iy1 * overlay.frameHeight) / sourceHeight;
    const x2 = (ix2 * overlay.frameWidth) / sourceWidth;
    const y2 = (iy2 * overlay.frameHeight) / sourceHeight;
    return {
      left: overlay.left + x1 * overlay.scale,
      top: overlay.top + y1 * overlay.scale,
      width: Math.max(1, (x2 - x1) * overlay.scale),
      height: Math.max(1, (y2 - y1) * overlay.scale),
    };
  }

  function submitQuestion(event) {
    event.preventDefault();
    const trimmed = question.trim();
    if (!trimmed) return;

    const contextLines = visibleMessages.map((message) => `${messageLabel(message.role)}：${message.content}`).join("\n");
    const answer = contextLines
      ? `基于当前已识别聊天记录：\n${contextLines}\n\n建议回复：${replyText}`
      : "当前还没有读取到聊天记录。请先确认监控服务已启动，并等待检测到新消息后再询问。";

    setQaMessages((current) => [
      ...current,
      { role: "user", content: trimmed },
      { role: "assistant", content: answer },
    ]);
    setQuestion("");
  }

  return (
    <div className="grid h-full min-h-0 grid-cols-[minmax(0,1fr)_minmax(320px,400px)] gap-4 p-4 max-lg:grid-cols-1">
      <section className="flex min-h-0 flex-col gap-4">
        <div className="panel flex min-h-0 flex-1 flex-col overflow-hidden p-4">
          <div className="mb-3 flex items-center justify-between gap-3">
            <div>
              <h2 className="text-[16px] font-extrabold">微信窗口实时画面</h2>
              <p className="mt-1 text-[12px] text-muted">
                {monitorEvent?.target_label ? `预览来源：${monitorEvent.target_label}` : `来自本地监控流：${MONITOR_ENDPOINT}/stream.mjpg`}
              </p>
            </div>
            <div className="flex shrink-0 items-center gap-2">
              <span className="tag">{streamFps ? `${streamFps.toFixed(1)} FPS` : "FPS --"}</span>
              <span className={`tag ${monitorEvent ? "text-primary" : ""}`}>{monitorEvent ? "在线" : "等待监控服务"}</span>
            </div>
          </div>
          <div id="wechat-preview-frame" className="relative min-h-0 flex-1 overflow-hidden rounded-[14px] border border-line bg-black">
            <img
              src={streamUrl}
              alt="微信窗口实时画面"
              className="h-full w-full object-contain"
              draggable={false}
              onError={() => {
                window.setTimeout(() => {
                  setStreamUrl(`${MONITOR_ENDPOINT}/frame.jpg?t=${Date.now()}`);
                }, 1000);
              }}
            />
            <div className="absolute left-3 top-3 rounded-full bg-black/70 px-3 py-1 font-mono text-[12px] font-bold text-[#86efac]">
              {streamFps ? `${streamFps.toFixed(1)} FPS` : "等待帧率"}
            </div>
            {annotation?.regions?.map((region) => {
              const style = regionStyle(region);
              if (!style) return null;
              return (
                <div
                  key={region.id}
                  className="pointer-events-none absolute rounded-[8px] border-2 border-[#22c55e] bg-[#22c55e]/10 shadow-[0_0_0_1px_rgba(0,0,0,.45)]"
                  style={style}
                >
                  <div className="absolute -left-0.5 -top-6 rounded bg-[#22c55e] px-2 py-0.5 text-[11px] font-black text-black shadow">
                    {region.type || region.name}
                  </div>
                </div>
              );
            })}
            {streamError ? (
              <div className="absolute inset-x-0 bottom-4 mx-auto w-fit max-w-[80%] rounded-full bg-black/75 px-4 py-2 text-center text-[12px] font-bold text-[#fca5a5]">
                {streamError}
              </div>
            ) : null}
          </div>
        </div>
      </section>

      <aside className="panel flex min-h-0 max-w-[400px] flex-col overflow-hidden p-4 max-lg:max-w-none">
        <div className="mb-3 shrink-0">
          <h2 className="text-[16px] font-extrabold">客户聊天记录</h2>
          <p className="mt-1 text-[12px] text-muted">展示最近一次 LLM 读取到的对话和建议回复。</p>
        </div>

        <div className="scrollbar-hidden min-h-0 flex-1 space-y-3 overflow-y-auto pr-1">
          <div className="rounded-[14px] border border-line bg-surface2 p-3">
            <div className="text-[11px] font-bold text-muted">最新客户消息</div>
            <div className="mt-2 text-[14px] font-bold leading-6">{latestUserMessage}</div>
          </div>

          <div className="space-y-2">
            {visibleMessages.length ? (
              visibleMessages.map((message, index) => (
                <div
                  key={`${message.role}-${message.content}-${index}`}
                  className={`rounded-[14px] p-3 ${message.role === "me" ? "bg-[var(--primary-soft)]" : "bg-surface2"}`}
                >
                  <div className="mb-1 flex items-center gap-2 text-[11px] font-black text-muted">
                    {message.role === "me" ? <UserRound size={13} /> : <Bot size={13} />}
                    {message.sender || messageLabel(message.role)}
                  </div>
                  <div className="text-[13px] leading-5">{message.content}</div>
                </div>
              ))
            ) : (
              <div className="rounded-[14px] border border-dashed border-line p-4 text-center text-[12px] text-muted">
                暂无聊天记录，等待监测到新消息后读取。
              </div>
            )}
          </div>

          <div className="rounded-[14px] border border-primary/30 bg-[var(--primary-soft)] p-3">
            <div className="text-[11px] font-black text-primary">建议回复</div>
            <div className="mt-2 text-[13px] leading-5">{replyText}</div>
          </div>

          {qaMessages.length ? (
            <div className="space-y-2 border-t border-line pt-3">
              {qaMessages.map((message, index) => (
                <div key={`${message.role}-${index}`} className="rounded-[12px] bg-surface2 p-3 text-[12px] leading-5">
                  <div className="mb-1 font-black text-muted">{message.role === "user" ? "我" : "AI"}</div>
                  <div className="whitespace-pre-wrap">{message.content}</div>
                </div>
              ))}
            </div>
          ) : null}
        </div>

        <form onSubmit={submitQuestion} className="mt-3 flex shrink-0 items-center gap-2 border-t border-line pt-3">
          <input
            value={question}
            onChange={(event) => setQuestion(event.target.value)}
            placeholder="询问客户信息或当前对话..."
            className="min-w-0 flex-1 rounded-[12px] border border-line bg-surface px-3 py-2 text-[13px] outline-none transition focus:border-primary"
          />
          <button className="btn-primary h-10 shrink-0 px-3" type="submit" aria-label="发送问题">
            <SendHorizontal size={16} strokeWidth={2.6} />
          </button>
        </form>
      </aside>
    </div>
  );
}
