import { useCallback, useMemo, useState } from "react";
import { MonacoEditor } from "../components/editor/MonacoEditor";
import { EditorTabs } from "../components/editor/EditorTabs";
import { GffEditor } from "../components/gff/GffEditor";
import { ItemEditor } from "../components/gff/ItemEditor";
import { CreatureEditor } from "../components/gff/CreatureEditor";
import { AreaEditor } from "../components/gff/AreaEditor";
import { DialogEditor } from "../components/gff/DialogEditor";
import { FileCode, Code2, Eye } from "lucide-react";

const GFF_EXTENSIONS = [".uti.json", ".utc.json", ".are.json", ".dlg.json", ".utp.json", ".utm.json"];

type GffEditorType = "uti" | "utc" | "are" | "dlg" | "generic" | null;

function isGffFile(tabKey: string): boolean {
  return GFF_EXTENSIONS.some((ext) => tabKey.endsWith(ext));
}

function getGffEditorType(tabKey: string): GffEditorType {
  if (tabKey.endsWith(".uti.json")) return "uti";
  if (tabKey.endsWith(".utc.json")) return "utc";
  if (tabKey.endsWith(".are.json")) return "are";
  if (tabKey.endsWith(".dlg.json")) return "dlg";
  if (tabKey.endsWith(".utp.json") || tabKey.endsWith(".utm.json")) return "generic";
  return null;
}

function repoFromTabKey(tabKey: string): string {
  const idx = tabKey.indexOf(":");
  return idx > 0 ? tabKey.slice(0, idx) : "";
}

function filePathFromTabKey(tabKey: string): string {
  const idx = tabKey.indexOf(":");
  return idx > 0 ? tabKey.slice(idx + 1) : tabKey;
}

interface EditorProps {
  editorState: ReturnType<typeof import("../hooks/useEditorState").useEditorState>;
  workspacePath?: string;
}

export function Editor({ editorState, workspacePath }: EditorProps) {
  const {
    openTabs,
    activeTab,
    dirtyFiles,
    selectTab,
    closeFile,
    updateContent,
    getContent,
    markClean,
  } = editorState;

  const [editorModes, setEditorModes] = useState<Record<string, "visual" | "raw">>({});

  const tabs = useMemo(
    () =>
      openTabs.map((path: string) => ({
        path,
        dirty: dirtyFiles.has(path),
      })),
    [openTabs, dirtyFiles],
  );

  const activeContent = activeTab ? (getContent(activeTab) ?? "") : "";
  const activeFilePath = activeTab ? filePathFromTabKey(activeTab) : "";
  const activeRepo = activeTab ? repoFromTabKey(activeTab) : "";

  const isActiveGff = activeTab ? isGffFile(activeTab) : false;
  const activeMode = activeTab
    ? editorModes[activeTab] ?? (isActiveGff ? "visual" : "raw")
    : "raw";

  const handleChange = useCallback(
    (value: string) => {
      if (activeTab) {
        updateContent(activeTab, value);
      }
    },
    [activeTab, updateContent],
  );

  const handleSwitchToRaw = useCallback(() => {
    if (activeTab) {
      setEditorModes((prev) => ({ ...prev, [activeTab]: "raw" }));
    }
  }, [activeTab]);

  const handleSwitchToVisual = useCallback(() => {
    if (activeTab) {
      setEditorModes((prev) => ({ ...prev, [activeTab]: "visual" }));
    }
  }, [activeTab]);

  const handleGffSave = useCallback(
    (newContent: string) => {
      if (activeTab) {
        updateContent(activeTab, newContent);
        markClean(activeTab);
      }
    },
    [activeTab, updateContent, markClean],
  );

  const renderEditor = () => {
    if (!activeTab) {
      return (
        <div
          style={{
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
            justifyContent: "center",
            height: "100%",
            gap: 12,
          }}
        >
          <FileCode
            size={48}
            style={{ color: "var(--forge-text-secondary)", opacity: 0.4 }}
          />
          <p
            style={{
              color: "var(--forge-text-secondary)",
              fontSize: "var(--text-lg)",
              fontFamily: "var(--font-heading)",
              margin: 0,
            }}
          >
            Open a file from the File Explorer to start editing
          </p>
        </div>
      );
    }

    if (isActiveGff && activeMode === "visual") {
      const editorType = getGffEditorType(activeTab);
      const commonProps = {
        key: activeTab,
        repo: activeRepo,
        filePath: activeFilePath,
        content: activeContent,
        onSave: handleGffSave,
        onSwitchToRaw: handleSwitchToRaw,
      };

      switch (editorType) {
        case "uti":
          return <ItemEditor {...commonProps} />;
        case "utc":
          return <CreatureEditor {...commonProps} />;
        case "are":
          return <AreaEditor {...commonProps} />;
        case "dlg":
          return <DialogEditor {...commonProps} />;
        default:
          return <GffEditor {...commonProps} />;
      }
    }

    return (
      <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
        {isActiveGff && activeMode === "raw" && (
          <div
            style={{
              display: "flex",
              alignItems: "center",
              justifyContent: "flex-end",
              flexShrink: 0,
              padding: "4px 16px",
              borderBottom: "1px solid var(--forge-border)",
              backgroundColor: "var(--forge-surface-raised)",
            }}
          >
            <button
              onClick={handleSwitchToVisual}
              style={{
                display: "inline-flex",
                alignItems: "center",
                gap: 6,
                padding: "4px 12px",
                borderRadius: 4,
                border: "1px solid var(--forge-border)",
                backgroundColor: "var(--forge-surface)",
                color: "var(--forge-text-secondary)",
                fontSize: "var(--text-xs)",
                fontFamily: "var(--font-mono)",
                cursor: "pointer",
              }}
            >
              <Eye size={13} />
              Switch to Visual Editor
            </button>
          </div>
        )}
        <div style={{ flex: 1, overflow: "hidden" }}>
          <MonacoEditor
            key={activeTab}
            filePath={activeFilePath}
            content={activeContent}
            onChange={handleChange}
            workspacePath={workspacePath}
          />
        </div>
      </div>
    );
  };

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        height: "100%",
        backgroundColor: "var(--forge-bg)",
      }}
    >
      <EditorTabs
        tabs={tabs}
        activeTab={activeTab}
        onSelect={selectTab}
        onClose={closeFile}
      />
      <div style={{ flex: 1, overflow: "hidden" }}>
        {renderEditor()}
      </div>
    </div>
  );
}
