import { useEffect, useMemo, useRef, useState } from "react";
import { App, Button, Card, List, Spin, Typography } from "antd";
import { LeftOutlined, ReloadOutlined, SaveOutlined, MenuFoldOutlined, MenuUnfoldOutlined } from "@ant-design/icons";
import { useNavigate, useParams } from "react-router";

import {
  getEditorProjectInfoUsingGet,
  getEditorTaskUsingGet,
  listEditorTasksUsingGet,
  upsertEditorAnnotationUsingPut,
} from "../annotation.api";

type EditorProjectInfo = {
  projectId: string;
  datasetId: string;
  templateId?: string | null;
  labelConfig?: string | null;
  supported: boolean;
  unsupportedReason?: string | null;
};

type EditorTaskListItem = {
  fileId: string;
  fileName: string;
  fileType?: string | null;
  hasAnnotation: boolean;
  annotationUpdatedAt?: string | null;
};

type LsfMessage = {
  type?: string;
  payload?: any;
};

const LSF_IFRAME_SRC = "/lsf/lsf.html";

export default function LabelStudioTextEditor() {
  const { projectId = "" } = useParams();
  const navigate = useNavigate();
  const { message } = App.useApp();

  const origin = useMemo(() => window.location.origin, []);
  const iframeRef = useRef<HTMLIFrameElement | null>(null);
  const initSeqRef = useRef(0);
  const expectedTaskIdRef = useRef<number | null>(null);

  const [loadingProject, setLoadingProject] = useState(true);
  const [loadingTasks, setLoadingTasks] = useState(false);
  const [loadingTaskDetail, setLoadingTaskDetail] = useState(false);
  const [saving, setSaving] = useState(false);

  const [iframeReady, setIframeReady] = useState(false);
  const [lsReady, setLsReady] = useState(false);
  const [project, setProject] = useState<EditorProjectInfo | null>(null);
  const [tasks, setTasks] = useState<EditorTaskListItem[]>([]);
  const [selectedFileId, setSelectedFileId] = useState<string>("");
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);

  const postToIframe = (type: string, payload?: any) => {
    const win = iframeRef.current?.contentWindow;
    if (!win) return;
    win.postMessage({ type, payload }, origin);
  };

  const loadProject = async () => {
    setLoadingProject(true);
    try {
      const resp = (await getEditorProjectInfoUsingGet(projectId)) as any;
      const data = resp?.data as EditorProjectInfo | undefined;
      if (!data?.projectId) {
        message.error("获取标注项目信息失败");
        setProject(null);
        return;
      }
      setProject(data);
    } catch (e) {
      console.error(e);
      message.error("获取标注项目信息失败");
      setProject(null);
    } finally {
      setLoadingProject(false);
    }
  };

  const loadTasks = async (silent = false) => {
    if (!projectId) return;
    if (!silent) setLoadingTasks(true);
    try {
      const resp = (await listEditorTasksUsingGet(projectId, { page: 0, size: 200 })) as any;
      const content = (resp?.data?.content || []) as EditorTaskListItem[];
      const items = Array.isArray(content) ? content : [];
      setTasks(items);
      if (!selectedFileId && items.length > 0) {
        setSelectedFileId(items[0].fileId);
      }
    } catch (e) {
      console.error(e);
      if (!silent) message.error("获取文件列表失败");
      setTasks([]);
    } finally {
      if (!silent) setLoadingTasks(false);
    }
  };

  const initEditorForFile = async (fileId: string) => {
    if (!project?.supported) return;
    if (!project?.labelConfig) {
      message.error("该项目未绑定标注模板，无法加载编辑器");
      return;
    }
    if (!iframeReady) return;

    const seq = ++initSeqRef.current;
    setLoadingTaskDetail(true);
    setLsReady(false);
    expectedTaskIdRef.current = null;

    try {
      const resp = (await getEditorTaskUsingGet(projectId, fileId)) as any;
      const task = resp?.data?.task;
      if (!task) {
        message.error("获取任务详情失败");
        return;
      }
      if (seq !== initSeqRef.current) return;

      expectedTaskIdRef.current = Number(task?.id) || null;
      postToIframe("LS_INIT", {
        labelConfig: project.labelConfig,
        task,
        user: { id: "datamate" },
        // 完整的 Label Studio 原生界面配置
        interfaces: [
          // 核心面板
          "panel",              // 导航面板（undo/redo/reset）
          "update",             // 更新按钮
          "submit",             // 提交按钮
          "controls",           // 控制面板
          // 侧边栏（包含 Outliner 和 Details）
          "side-column",
          // 标注管理
          "annotations:tabs",
          "annotations:menu",
          "annotations:current",
          "annotations:add-new",
          "annotations:delete",
          "annotations:view-all",
          // 预测
          "predictions:tabs",
          "predictions:menu",
          // 其他
          "auto-annotation",
          "edit-history",
        ],
        selectedAnnotationIndex: 0,
        allowCreateEmptyAnnotation: true,
      });
    } catch (e) {
      console.error(e);
      message.error("加载编辑器失败");
    } finally {
      if (seq === initSeqRef.current) setLoadingTaskDetail(false);
    }
  };

  const saveFromExport = async (payload: any) => {
    const fileId = payload?.fileId;
    const annotation = payload?.annotation;
    if (!fileId || !annotation) {
      message.error("导出标注失败：缺少 fileId/annotation");
      return;
    }

    setSaving(true);
    try {
      await upsertEditorAnnotationUsingPut(projectId, String(fileId), { annotation });
      message.success("标注已保存");
      await loadTasks(true);
    } catch (e) {
      console.error(e);
      message.error("保存失败");
    } finally {
      setSaving(false);
    }
  };

  const requestExport = () => {
    if (!selectedFileId) {
      message.warning("请先选择文件");
      return;
    }
    postToIframe("LS_EXPORT", {});
  };

  useEffect(() => {
    setIframeReady(false);
    setProject(null);
    setTasks([]);
    setSelectedFileId("");
    initSeqRef.current = 0;
    setLsReady(false);
    expectedTaskIdRef.current = null;

    if (projectId) loadProject();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [projectId]);

  useEffect(() => {
    if (!project?.supported) return;
    loadTasks();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [project?.projectId, project?.supported]);

  useEffect(() => {
    if (!selectedFileId) return;
    initEditorForFile(selectedFileId);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedFileId, iframeReady]);

  useEffect(() => {
    const handler = (event: MessageEvent<LsfMessage>) => {
      if (event.origin !== origin) return;
      const msg = event.data || {};
      if (!msg?.type) return;

      if (msg.type === "LS_IFRAME_READY") {
        setIframeReady(true);
        return;
      }

      if (msg.type === "LS_READY") {
        const readyTaskId = msg.payload?.taskId;
        if (expectedTaskIdRef.current && readyTaskId) {
          if (Number(readyTaskId) !== expectedTaskIdRef.current) return;
        }
        setLsReady(true);
        return;
      }

      if (msg.type === "LS_EXPORT_RESULT") {
        saveFromExport(msg.payload);
        return;
      }

      // 兼容 iframe 内部在 submit 时直接上报（若启用）
      if (msg.type === "LS_SUBMIT") {
        saveFromExport(msg.payload);
        return;
      }

      if (msg.type === "LS_ERROR") {
        message.error(msg.payload?.message || "编辑器发生错误");
        setLsReady(false);
      }
    };

    window.addEventListener("message", handler);
    return () => window.removeEventListener("message", handler);
  }, [message, origin]);

  if (loadingProject) {
    return (
      <div className="h-full flex items-center justify-center">
        <Spin />
      </div>
    );
  }

  if (!project) {
    return (
      <div className="h-full flex items-center justify-center">
        <Card>
          <Typography.Text>未找到标注项目</Typography.Text>
          <div className="mt-4 flex justify-end">
            <Button onClick={() => navigate("/data/annotation")}>返回</Button>
          </div>
        </Card>
      </div>
    );
  }

  if (!project.supported) {
    return (
      <div className="h-full flex items-center justify-center">
        <Card style={{ maxWidth: 640 }}>
          <Typography.Title level={4}>暂不支持该数据类型</Typography.Title>
          <Typography.Paragraph type="secondary">
            {project.unsupportedReason || "当前仅支持文本（TEXT）项目的内嵌编辑器。"}
          </Typography.Paragraph>
          <div className="flex justify-end gap-2">
            <Button onClick={() => navigate("/data/annotation")}>返回</Button>
          </div>
        </Card>
      </div>
    );
  }

  return (
    <div className="h-full flex flex-col">
      {/* 顶部工具栏 */}
      <div className="flex items-center justify-between px-3 py-2 border-b border-gray-200 bg-white">
        <div className="flex items-center gap-2">
          <Button icon={<LeftOutlined />} onClick={() => navigate("/data/annotation")}>
            返回
          </Button>
          <Button
            icon={sidebarCollapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
            onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
            title={sidebarCollapsed ? "展开文件列表" : "收起文件列表"}
          />
          <Typography.Title level={5} style={{ margin: 0 }}>
            标注编辑器
          </Typography.Title>
        </div>
        <div className="flex items-center gap-2">
          <Button icon={<ReloadOutlined />} loading={loadingTasks} onClick={() => loadTasks()}>
            刷新
          </Button>
          <Button
            type="primary"
            icon={<SaveOutlined />}
            loading={saving}
            disabled={!iframeReady || !selectedFileId}
            onClick={requestExport}
          >
            保存
          </Button>
        </div>
      </div>

      {/* 主体区域 */}
      <div className="flex flex-1 min-h-0">
        {/* 左侧文件列表 - 可折叠 */}
        <div
          className="border-r border-gray-200 bg-gray-50 flex flex-col transition-all duration-200"
          style={{ width: sidebarCollapsed ? 0 : 240, overflow: "hidden" }}
        >
          <div className="px-3 py-2 border-b border-gray-200 bg-white font-medium text-sm">
            文件列表
          </div>
          <div className="flex-1 overflow-auto">
            <List
              loading={loadingTasks}
              size="small"
              dataSource={tasks}
              renderItem={(item) => (
                <List.Item
                  key={item.fileId}
                  className="cursor-pointer hover:bg-blue-50"
                  style={{
                    background: item.fileId === selectedFileId ? "#e6f4ff" : undefined,
                    padding: "8px 12px",
                    borderBottom: "1px solid #f0f0f0",
                  }}
                  onClick={() => setSelectedFileId(item.fileId)}
                >
                  <div className="flex flex-col w-full gap-1">
                    <Typography.Text ellipsis style={{ fontSize: 13 }}>
                      {item.fileName}
                    </Typography.Text>
                    <div className="flex items-center justify-between">
                      <Typography.Text
                        type={item.hasAnnotation ? "success" : "secondary"}
                        style={{ fontSize: 11 }}
                      >
                        {item.hasAnnotation ? "已标注" : "未标注"}
                      </Typography.Text>
                      {item.annotationUpdatedAt && (
                        <Typography.Text type="secondary" style={{ fontSize: 10 }}>
                          {item.annotationUpdatedAt}
                        </Typography.Text>
                      )}
                    </div>
                  </div>
                </List.Item>
              )}
            />
          </div>
        </div>

        {/* 右侧编辑器 - Label Studio iframe */}
        <div className="flex-1 relative">
          {(!iframeReady || loadingTaskDetail || (selectedFileId && !lsReady)) && (
            <div className="absolute inset-0 z-10 flex items-center justify-center bg-white/80">
              <Spin
                tip={
                  !iframeReady
                    ? "编辑器资源加载中..."
                    : loadingTaskDetail
                      ? "任务数据加载中..."
                      : "编辑器初始化中..."
                }
              />
            </div>
          )}
          <iframe
            ref={iframeRef}
            title="Label Studio Frontend"
            src={LSF_IFRAME_SRC}
            className="w-full h-full border-0"
          />
        </div>
      </div>
    </div>
  );
}
