"use client";

import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Loader2, Table, X, Zap } from "lucide-react";
import type { DocumentTable, TableRowData } from "@/types/online-table";
import {
  DEFAULT_TABLE_COLUMNS,
  DEFAULT_TABLE_ROWS,
  DEFAULT_TABLE_SCHEMA,
  createDefaultTableSnapshot,
  saveOnlineTable,
} from "@/lib/online-table";
import { useDebouncedCallback } from "@/hooks/use-debounced-callback";
import { useLuckysheetLoader } from "@/components/online-table/useLuckysheetLoader";
import { extractRowsForPreview } from "@/components/online-table/utils";

interface FullScreenTableEditorProps {
  tableId: string;
  onClose: () => void;
}

// Luckysheet 容器的 ID
const LUCKY_SHEET_CONTAINER_ID = "luckysheet-editor-container";

type LuckysheetSelection =
  | {
      row?: [number, number];
      column?: [number, number];
      row_focus?: number;
      column_focus?: number;
    }
  | undefined;

const ENABLE_SINGLE_CLICK_EDIT = true;

const isPrintableKey = (event: KeyboardEvent) => {
  if (event.defaultPrevented) return false;
  if (event.metaKey || event.ctrlKey || event.altKey) return false;
  if (event.key === "Enter" || event.key === "Tab" || event.key === "Escape") return false;
  if (event.key.length === 1) return true;
  return event.key === "Process" || event.key === "Unidentified";
};

const isInlineEditorVisible = () => {
  const inputBox = document.getElementById("luckysheet-input-box");
  if (!inputBox) {
    return false;
  }
  const style = window.getComputedStyle(inputBox);
  return style.top !== "-10000px" && style.display !== "none";
};

const isElementInsideEditorToolbar = (element: HTMLElement | null) => {
  if (!element) return false;
  if (element.closest(".luckysheet-wa-editor")) {
    return true;
  }
  if (element.closest(".luckysheet-modal-dialog")) {
    return true;
  }
  return false;
};

const FullScreenTableEditor: React.FC<FullScreenTableEditorProps> = ({ tableId, onClose }) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const isApplyingSnapshotRef = useRef(false);
  const hasInitializedRef = useRef(false);
  const lastTableIdRef = useRef<string | null>(null);
  const isLuckysheetReady = useLuckysheetLoader();
  const [tableData, setTableData] = useState<DocumentTable | null>(null);
  const [isTableLoading, setIsTableLoading] = useState(true);
  const [tableError, setTableError] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [hasPendingChanges, setHasPendingChanges] = useState(false);
  const [saveError, setSaveError] = useState<string | null>(null);
  const [lastSyncedAt, setLastSyncedAt] = useState<number | null>(null);
  const persistSnapshotRef = useRef<((reason: "auto" | "close") => Promise<void>) | null>(null);
  const lastPointerDownInGridRef = useRef(false);
  const savingHintTimerRef = useRef<number | null>(null);
  const [showSavingHint, setShowSavingHint] = useState(false);
  const [isRenaming, setIsRenaming] = useState(false);
  const [renameValue, setRenameValue] = useState("");
  const [isSavingTitle, setIsSavingTitle] = useState(false);

  const startSavingHint = useCallback(() => {
    if (savingHintTimerRef.current !== null) return;
    savingHintTimerRef.current = window.setTimeout(() => {
      setShowSavingHint(true);
    }, 700);
  }, []);

  const stopSavingHint = useCallback(() => {
    if (savingHintTimerRef.current !== null) {
      clearTimeout(savingHintTimerRef.current);
      savingHintTimerRef.current = null;
    }
    setShowSavingHint(false);
  }, []);

  useEffect(() => {
    if (typeof window !== "undefined") {
      (window as unknown as { __wolaiFullScreenState?: { isLoaded: boolean; tableReady: boolean } }).__wolaiFullScreenState = {
        isLoaded: isLuckysheetReady,
        tableReady: !!tableData,
      };
    }
  }, [isLuckysheetReady, tableData]);

  const fetchTable = useCallback((id: string) => {
    setIsTableLoading(true);
    setTableError(null);
    setTableData(null);
    fetch(`/api/tables/${id}`)
      .then((response) => {
        if (!response.ok) {
          throw new Error(`Failed to load table ${id}`);
        }
        return response.json() as Promise<DocumentTable>;
      })
      .then((data) => {
        setTableData(data);
      })
      .catch((error) => {
        console.error(error);
        setTableError("无法加载表格数据，请稍后重试。");
        setTableData(null);
      })
      .finally(() => setIsTableLoading(false));
  }, []);

  useEffect(() => {
    fetchTable(tableId);
    hasInitializedRef.current = false;
    lastTableIdRef.current = tableId;
  }, [fetchTable, tableId]);

  useEffect(() => {
    if (tableData) {
      setIsTableLoading(false);
    }
  }, [tableData]);

  useEffect(() => {
    if (tableData?.title !== undefined) {
      setRenameValue(tableData.title ?? "");
    }
  }, [tableData?.title]);

  const luckysheetSheets = useMemo(() => {
    if (tableData?.snapshot?.luckysheet && Array.isArray(tableData.snapshot.luckysheet) && tableData.snapshot.luckysheet.length > 0) {
      return tableData.snapshot.luckysheet;
    }
    const snapshot = createDefaultTableSnapshot(tableData?.schema ?? DEFAULT_TABLE_SCHEMA);
    return snapshot.luckysheet ?? [];
  }, [tableData]);

  const normalizedSheets = useMemo(() => {
    return luckysheetSheets.map((sheet: any) => ({
      ...sheet,
      celldata: Array.isArray(sheet.celldata) ? sheet.celldata : [],
      config: {
        ...(sheet.config ?? {}),
        rowlen: { ...(sheet.config?.rowlen ?? {}) },
        columnlen: { ...(sheet.config?.columnlen ?? {}) },
        merge: { ...(sheet.config?.merge ?? {}) },
      },
    }));
  }, [luckysheetSheets]);

  const persistSnapshot = useCallback(async (reason: "auto" | "close") => {
    if (!tableData || !window.luckysheet || typeof window.luckysheet.getluckysheetfile !== "function") {
      return;
    }
    startSavingHint();
    setIsSaving(true);
    setSaveError(null);
    try {
      const luckysheetData = window.luckysheet.getluckysheetfile?.() ?? luckysheetSheets;
      const rows = extractRowsForPreview(
        luckysheetData,
        (tableData.schema?.columns ?? []).map((item) => ({ id: item.id })),
      ).filter((row) => row && typeof row === "object" && Object.keys(row).length > 0);
      const snapshot = {
        ...(tableData.snapshot ?? {}),
        rows,
        luckysheet: Array.isArray(luckysheetData) ? luckysheetData : luckysheetSheets,
      };
      await saveOnlineTable(tableId, {
        snapshot,
        rows,
        schema: tableData.schema,
      });
      setHasPendingChanges(false);
      setLastSyncedAt(Date.now());
      window.dispatchEvent(new CustomEvent("online-table-saved", { detail: { tableId } }));
    } catch (error) {
      console.error("保存 Luckysheet 数据失败", error);
      setSaveError(reason === "close" ? "关闭前保存失败，请重试" : "自动保存失败");
    } finally {
      stopSavingHint();
      setIsSaving(false);
    }
  }, [startSavingHint, stopSavingHint, tableData, tableId]);

  const debouncedPersist = useDebouncedCallback(() => {
    void persistSnapshot("auto");
  }, 1200);

  useEffect(() => {
    persistSnapshotRef.current = persistSnapshot;
  }, [persistSnapshot]);

  useEffect(() => {
    return () => {
      debouncedPersist.cancel();
      void persistSnapshotRef.current?.("close");
      stopSavingHint();
    };
  }, [debouncedPersist, stopSavingHint]);

  useEffect(() => {
    if (!isLuckysheetReady) {
      lastPointerDownInGridRef.current = false;
      return;
    }
    const container = document.getElementById(LUCKY_SHEET_CONTAINER_ID);
    if (!container) {
      return;
    }
    const handlePointerDownInside = () => {
      lastPointerDownInGridRef.current = true;
    };
    const handlePointerDownDocument = (event: PointerEvent) => {
      if (!(event.target instanceof Node)) {
        return;
      }
      if (!container.contains(event.target)) {
        lastPointerDownInGridRef.current = false;
      }
    };
    container.addEventListener("pointerdown", handlePointerDownInside);
    document.addEventListener("pointerdown", handlePointerDownDocument);
    return () => {
      container.removeEventListener("pointerdown", handlePointerDownInside);
      document.removeEventListener("pointerdown", handlePointerDownDocument);
    };
  }, [isLuckysheetReady]);

  const focusLuckysheetEditor = useCallback(() => {
    const applyFocus = () => {
      const editor = document.getElementById("luckysheet-rich-text-editor");
      if (editor && typeof editor.focus === "function") {
        editor.focus();
        const selection = window.getSelection();
        if (selection && editor.childNodes.length > 0) {
          const range = document.createRange();
          range.selectNodeContents(editor);
          range.collapse(false);
          selection.removeAllRanges();
          selection.addRange(range);
        }
      }
    };
    requestAnimationFrame(() => {
      applyFocus();
      setTimeout(applyFocus, 0);
    });
  }, []);

  const shouldAutoFocusEditor = useCallback(
    (target: EventTarget | null) => {
      if (!isLuckysheetReady || !tableData) {
        return false;
      }
      const container = document.getElementById(LUCKY_SHEET_CONTAINER_ID);
      if (!container) {
        return false;
      }
      const editor = document.getElementById("luckysheet-rich-text-editor");
      if (!editor || document.activeElement === editor) {
        return false;
      }

      const targetElement = target instanceof HTMLElement ? target : null;
      if (isElementInsideEditorToolbar(targetElement)) {
        return false;
      }

      const activeElement = document.activeElement as HTMLElement | null;
      if (isElementInsideEditorToolbar(activeElement)) {
        return false;
      }

      if (targetElement && container.contains(targetElement)) {
        return true;
      }
      if (activeElement && container.contains(activeElement)) {
        return true;
      }
      return lastPointerDownInGridRef.current;
    },
    [isLuckysheetReady, tableData],
  );

  const ensureInlineEditor = useCallback(
    (target: EventTarget | null) => {
      if (!shouldAutoFocusEditor(target)) {
        return false;
      }
      if (isApplyingSnapshotRef.current) {
        return false;
      }
      if (!window.luckysheet || typeof window.luckysheet.enterEditMode !== "function") {
        return false;
      }
      window.luckysheet.enterEditMode();
      focusLuckysheetEditor();
      return true;
    },
    [focusLuckysheetEditor, shouldAutoFocusEditor],
  );

  useEffect(() => {
    if (!isLuckysheetReady) {
      return;
    }
    const handleKeydown = (event: KeyboardEvent) => {
      if (!isPrintableKey(event)) {
        return;
      }
      ensureInlineEditor(event.target);
    };
    const handleCompositionStart = (event: CompositionEvent) => {
      ensureInlineEditor(event.target);
    };
    window.addEventListener("keydown", handleKeydown, true);
    window.addEventListener("compositionstart", handleCompositionStart, true);
    return () => {
      window.removeEventListener("keydown", handleKeydown, true);
      window.removeEventListener("compositionstart", handleCompositionStart, true);
    };
  }, [ensureInlineEditor, isLuckysheetReady]);

  const isSingleCellSelection = useCallback((range: LuckysheetSelection[] | undefined) => {
    if (!Array.isArray(range) || range.length !== 1) {
      return false;
    }
    const target = range[0];
    if (!target) {
      return false;
    }
    const rowRange = target.row ?? (typeof target.row_focus === "number" ? [target.row_focus, target.row_focus] : undefined);
    const columnRange = target.column ?? (typeof target.column_focus === "number" ? [target.column_focus, target.column_focus] : undefined);
    if (!rowRange || !columnRange) {
      return false;
    }
    return rowRange[0] === rowRange[1] && columnRange[0] === columnRange[1];
  }, []);

  const tryEnterSingleClickEdit = useCallback(
    (range: LuckysheetSelection[] | undefined) => {
      if (!ENABLE_SINGLE_CLICK_EDIT) {
        return;
      }
      if (isApplyingSnapshotRef.current) {
        return;
      }
      if (typeof window === "undefined") {
        return;
      }
      const luckysheetInstance = window.luckysheet;
      if (!luckysheetInstance || typeof luckysheetInstance.enterEditMode !== "function") {
        return;
      }
      if (!isSingleCellSelection(range)) {
        return;
      }
    setTimeout(() => {
      const editor = document.getElementById("luckysheet-rich-text-editor");
      if (editor && document.activeElement === editor && isInlineEditorVisible()) {
        return;
      }
      luckysheetInstance.enterEditMode?.();
      focusLuckysheetEditor();
    }, 0);
    },
    [focusLuckysheetEditor, isSingleCellSelection],
  );

  useEffect(() => {
    if (!isLuckysheetReady) {
      return;
    }
    const container = document.getElementById(LUCKY_SHEET_CONTAINER_ID);
    if (!container) {
      return;
    }
    const handlePointerUp: EventListener = (event) => {
      const target = event.target instanceof Node ? event.target : null;
      if (target && !container.contains(target)) {
        return;
      }
      containerRef.current?.focus();
      requestAnimationFrame(() => {
        const selection = window.luckysheet?.getluckysheet_select_save?.();
        if (!selection) {
          return;
        }
        const normalized = Array.isArray(selection)
          ? (selection as LuckysheetSelection[])
          : [selection as LuckysheetSelection];
        tryEnterSingleClickEdit(normalized);
      });
    };
    const events = ["pointerup", "mouseup", "touchend"] as const;
    events.forEach((eventName) => {
      container.addEventListener(eventName, handlePointerUp, true);
    });
    return () => {
      events.forEach((eventName) => {
        container.removeEventListener(eventName, handlePointerUp, true);
      });
    };
  }, [isLuckysheetReady, tryEnterSingleClickEdit]);

  // Luckysheet 初始化和清理
  useEffect(() => {
    if (!isLuckysheetReady || !tableData || !containerRef.current || !window.luckysheet) {
      return;
    }

    if (hasInitializedRef.current && lastTableIdRef.current === tableId) {
      return;
    }

    hasInitializedRef.current = true;
    isApplyingSnapshotRef.current = true;

    if (containerRef.current.children.length > 0) {
      window.luckysheet?.destroy?.(LUCKY_SHEET_CONTAINER_ID);
      containerRef.current.innerHTML = "";
    }

    const gridKey = tableData?.grid_key ?? tableId;
    const loadUrl = gridKey ? `/api/luckysheet/load?gridKey=${gridKey}` : "";
    const options = {
      container: LUCKY_SHEET_CONTAINER_ID,
      title: tableData.title ?? tableId,
      lang: "zh",
      showinfobar: false,
      showtoolbar: true,
      showsheetbar: true,
      showstatisticBar: true,
      allowEdit: true,
      row: DEFAULT_TABLE_ROWS,
      column: DEFAULT_TABLE_COLUMNS,
      data: normalizedSheets,
      allowUpdate: false,
      gridKey,
      loadUrl,
      pointEdit: true,
      pointEditZoom: typeof window !== "undefined" && window.devicePixelRatio ? window.devicePixelRatio : 1,
      uploadImage: async (file: File) => {
        const formData = new FormData();
        formData.append("image", file);
        const response = await fetch("/api/luckysheet/upload-image", {
          method: "POST",
          body: formData,
        });
        const payload = await response.json().catch(() => null);
        if (!response.ok || !payload?.url) {
          throw new Error(payload?.msg ?? "上传图片失败");
        }
        return payload.url as string;
      },
      imageUrlHandle: (url: string) => url,
      hook: {
        workbookCreateAfter: () => {
          setIsTableLoading(false);
        },
        updated: () => {
          if (isApplyingSnapshotRef.current) return;
          setHasPendingChanges(true);
          debouncedPersist();
        },
        cellEditBefore: () => {
          focusLuckysheetEditor();
        },
        rangeSelect: (_sheet: unknown, selectedRange: LuckysheetSelection[] | LuckysheetSelection | undefined) => {
          const normalizedRange = Array.isArray(selectedRange)
            ? (selectedRange as LuckysheetSelection[])
            : selectedRange
              ? [selectedRange]
              : undefined;
          focusLuckysheetEditor();
          tryEnterSingleClickEdit(normalizedRange);
        },
        rangeMoveAfter: (_oldRange: LuckysheetSelection[] | undefined, newRange: LuckysheetSelection[] | undefined) => {
          focusLuckysheetEditor();
          tryEnterSingleClickEdit(newRange);
        },
      },
    };

    if (process.env.NODE_ENV !== "production") {
       
      console.log("[FullScreenTableEditor] init luckysheet", { tableId, sheets: options.data });
    }
    try {
      window.luckysheet?.create?.(options as any);
    } catch (error) {
      console.error("Luckysheet 初始化失败", error);
      setTableError("Luckysheet 初始化失败，请重试");
      isApplyingSnapshotRef.current = false;
      return;
    }

    // 等待首帧渲染完成再开放 updated 事件
    setTimeout(() => {
      isApplyingSnapshotRef.current = false;
    }, 0);

    return () => {
      if (window.luckysheet) {
        window.luckysheet?.destroy?.(LUCKY_SHEET_CONTAINER_ID);
      }
      if (containerRef.current) {
        containerRef.current.innerHTML = "";
      }
      hasInitializedRef.current = false;
    };
  }, [debouncedPersist, normalizedSheets, isLuckysheetReady, tableData, tableId, focusLuckysheetEditor, tryEnterSingleClickEdit]);

  const handleClose = async () => {
    await persistSnapshot("close");
    onClose();
  };

  const showLoadingOverlay = !isLuckysheetReady || isTableLoading;
  const loadingMessage = !isLuckysheetReady ? "正在加载 Luckysheet 资源..." : "正在加载表格数据...";

  const handleRenameSubmit = useCallback(async () => {
    if (!tableData) {
      setIsRenaming(false);
      return;
    }
    const nextTitle = (renameValue || "").trim() || "未命名表格";
    if (nextTitle === tableData.title) {
      setIsRenaming(false);
      return;
    }
    setIsSavingTitle(true);
    try {
      const updated = await saveOnlineTable(tableId, { title: nextTitle });
      const finalTitle = updated.title ?? nextTitle;
      setTableData((prev) => (prev ? { ...prev, title: finalTitle } : prev));
      window.dispatchEvent(new CustomEvent("online-table-saved", { detail: { tableId } }));
    } catch (error) {
      console.error("重命名表格失败", error);
      setRenameValue(tableData.title ?? "");
    } finally {
      setIsRenaming(false);
      setIsSavingTitle(false);
    }
  }, [renameValue, tableData, tableId]);

  const statusText = saveError
    ? saveError
    : isSaving && showSavingHint
      ? "同步中..."
      : hasPendingChanges
        ? "有未保存变更"
        : lastSyncedAt
          ? `已同步 ${new Date(lastSyncedAt).toLocaleTimeString()}`
          : "准备就绪";

  return (
    <div className="fixed inset-0 z-50 bg-white dark:bg-gray-900 flex flex-col">
      {/* 顶部工具栏 */}
      <header className="flex justify-between items-center p-3 border-b border-gray-200 shadow-sm">
        <div className="flex items-center space-x-3">
          <Table className="h-5 w-5 text-blue-500" />
          {isRenaming ? (
            <input
              autoFocus
              className="w-64 rounded border border-gray-200 px-2 py-1 text-lg font-semibold text-gray-800 focus:border-emerald-500 focus:outline-none"
              value={renameValue}
              onChange={(e) => setRenameValue(e.target.value)}
              onBlur={handleRenameSubmit}
              onKeyDown={(e) => {
                if (e.key === "Enter") {
                  e.preventDefault();
                  void handleRenameSubmit();
                }
                if (e.key === "Escape") {
                  e.preventDefault();
                  setRenameValue(tableData?.title ?? "");
                  setIsRenaming(false);
                }
              }}
            />
          ) : (
            <button
              type="button"
              className="flex items-center gap-2 text-left text-lg font-bold text-gray-900 hover:text-emerald-600"
              onClick={() => setIsRenaming(true)}
              title="点击重命名表格"
            >
              <span className="truncate max-w-xs">
                在线表格编辑 - {(tableData?.title ?? tableId).slice(0, 24)}
              </span>
              {isSavingTitle && <Loader2 className="h-4 w-4 animate-spin text-gray-400" />}
            </button>
          )}
          <Zap className="h-4 w-4 text-yellow-500" />
          <span className="text-xs text-yellow-600 font-medium" title="协同模式">协同模式 (单用户模式)</span>
        </div>
        <div className="flex items-center space-x-3">
          <span className="text-xs text-gray-500">{statusText}</span>
          <button
            onClick={handleClose}
            className="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
            title="退出并保存"
          >
            {isSaving ? <Loader2 className="h-5 w-5 animate-spin" /> : <X className="h-5 w-5" />}
          </button>
        </div>
      </header>
      
      {/* Luckysheet 容器 */}
      <div 
        id={LUCKY_SHEET_CONTAINER_ID} 
        ref={containerRef} 
        className="flex-grow w-full h-full"
        tabIndex={-1}
        aria-label="在线表格全屏编辑区域"
        style={{ display: isLuckysheetReady && !isTableLoading && !tableError ? "block" : "none" }}
      />

      {showLoadingOverlay && (
        <div className="flex justify-center items-center h-full text-gray-500 border border-dashed">
          <p>{loadingMessage}</p>
        </div>
      )}

      {tableError && !showLoadingOverlay && (
        <div className="flex flex-col justify-center items-center h-full text-red-500 border border-dashed space-y-2">
          <p>{tableError}</p>
          <button
            type="button"
            className="px-3 py-1 rounded-md border border-red-300 text-sm"
            onClick={() => fetchTable(tableId)}
          >
            重试
          </button>
        </div>
      )}
    </div>
  );
};

export default FullScreenTableEditor;
