import { useEffect, useState } from "react";
import { DownloadSimple, FolderOpen, ImageSquare, Stack } from "@phosphor-icons/react";
import type { ImageStudioApp } from "@app/app";
import { commandIds } from "@commands/ids";
import { BottomControlsIsland } from "./BottomControlsIsland";
import { CanvasViewport } from "./CanvasViewport";
import { LayersSheet } from "./LayersSheet";
import { ToolOverlay } from "./ToolOverlay";
import { labelForTool } from "./toolLabels";
import { resolveTransformTargetBounds, selectedTransformTarget } from "@editor/transform-targets";
import { handleDeleteSelectionKey, handleHistoryKey, keybindEventFromKeyboardEvent } from "@input/index";
import { useAppState } from "./useAppState";
import { downloadArtboardPng } from "./exportArtboardPng";
import { useImageImport } from "./useImageImport";
import { useViewportActivityIsland } from "./useViewportActivityIsland";
import "./index.css";

export type AppProps = {
  app: ImageStudioApp;
};

export function App({ app }: AppProps) {
  const state = useAppState(app.store);
  const zoomPercent = Math.round(state.editor.viewport.zoom * 100);
  const viewportActivityIsland = useViewportActivityIsland(state.editor.viewport);
  const imageImport = useImageImport(app.store);
  const [layersOpen, setLayersOpen] = useState(false);
  const transformTarget = state.editor.transformSession?.target ?? selectedTransformTarget(state.document, state.editor.selection);
  const activeArtboard = state.document.artboards.find((artboard) => artboard.id === state.editor.selection.artboardId) ?? state.document.artboards[0];
  const activeToolLabel = state.editor.maskEdit ? "Mask edit" : labelForTool(state.editor.tools.activeTool);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      const target = event.target;
      const editableTarget =
        target instanceof HTMLElement &&
        (target.isContentEditable || target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement);

      if (editableTarget) return;

      const historyConsumed = handleHistoryKey({ event: keybindEventFromKeyboardEvent(event), dispatch: app.store.dispatch });
      if (historyConsumed) {
        event.preventDefault();
        return;
      }

      if (event.altKey || event.ctrlKey || event.metaKey) return;

      if (event.key === "Escape" && app.store.getState().editor.maskEdit) {
        app.store.dispatch(commandIds.toolExitMaskEdit, undefined);
        event.preventDefault();
        return;
      }

      if (event.key.toLowerCase() === "l") {
        setLayersOpen(true);
        event.preventDefault();
        return;
      }

      const consumed = handleDeleteSelectionKey({
        event: keybindEventFromKeyboardEvent(event),
        selection: app.store.getState().editor.selection,
        dispatch: app.store.dispatch,
      });
      if (consumed) event.preventDefault();
    };

    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [app.store]);
  const transformBounds = transformTarget ? resolveTransformTargetBounds(state.document, transformTarget) : undefined;

  return (
    <main className="relative h-full overflow-hidden bg-background text-foreground">
      {imageImport.input}
      <header className="pointer-events-none absolute inset-x-3 top-3 z-10 flex h-12 items-center justify-between gap-3 rounded-2xl border border-white/10 bg-zinc-950/85 px-2.5 text-white shadow-2xl shadow-black/35 backdrop-blur-xl">
        <div className="flex min-w-0 items-center gap-3 pl-1.5">
          <div className="grid size-7 place-items-center rounded-lg bg-white text-black shadow-sm">
            <ImageSquare size={18} weight="fill" />
          </div>
          <div className="min-w-0">
            <h1 className="truncate text-sm font-semibold leading-4 tracking-wide">Image Studio</h1>
            <div className="truncate text-[11px] leading-4 text-white/45">{state.document.name}</div>
          </div>
        </div>

        <div className="hidden min-w-0 flex-1 items-center justify-center gap-1.5 md:flex">
          <span className={topBarChipClass()}>{activeToolLabel}</span>
          <span className={topBarChipClass()}>{zoomPercent}%</span>
          <span className={topBarChipClass()}>
            {state.editor.viewport.size.w}×{state.editor.viewport.size.h}
          </span>
          {activeArtboard ? <span className="truncate rounded-full bg-sky-400/15 px-3 py-1 text-xs font-medium text-sky-100 ring-1 ring-sky-300/20">{activeArtboard.name}</span> : null}
        </div>

        <div className="pointer-events-auto flex items-center gap-1.5">
          <button type="button" className={topBarButtonClass()} onClick={imageImport.openFilePicker}>
            <FolderOpen size={16} />
            <span className="hidden sm:inline">Import</span>
          </button>
          <button type="button" className={topBarButtonClass()} disabled={!activeArtboard} onClick={() => activeArtboard && void downloadArtboardPng(activeArtboard, state.document.assets)}>
            <DownloadSimple size={16} />
            <span className="hidden sm:inline">Export</span>
          </button>
          <button type="button" className={topBarButtonClass(layersOpen)} aria-pressed={layersOpen} onClick={() => setLayersOpen((open) => !open)}>
            <Stack size={16} weight={layersOpen ? "fill" : "regular"} />
            <span className="hidden sm:inline">Layers</span>
          </button>
        </div>
      </header>
      <div className="absolute left-3 top-1/2 z-10 -translate-y-1/2">
        <ToolOverlay
          activeTool={state.editor.tools.activeTool}
          interactionMode={state.editor.tools.interactionMode}
          dispatch={app.store.dispatch}
        />
      </div>
      <LayersSheet
        document={state.document}
        selection={state.editor.selection}
        maskEdit={state.editor.maskEdit}
        open={layersOpen}
        dispatch={app.store.dispatch}
      />
      <div className="absolute inset-x-0 bottom-4 z-10 flex justify-center">
        <BottomControlsIsland
          viewport={state.editor.viewport}
          visible={state.editor.tools.activeTool === "brush" || state.editor.tools.activeTool === "eraser" || Boolean(transformBounds) || viewportActivityIsland.visible}
          action={viewportActivityIsland.action}
          activeTool={state.editor.tools.activeTool}
          brushSettings={state.editor.tools.brush}
          editingMask={Boolean(state.editor.maskEdit)}
          maskViewMode={state.editor.maskEdit?.viewMode ?? "composite"}
          transformBounds={viewportActivityIsland.visible ? undefined : transformBounds}
          transformTarget={viewportActivityIsland.visible ? undefined : transformTarget}
          dispatch={app.store.dispatch}
        />
      </div>
      <CanvasViewport store={app.store} />
    </main>
  );
}

function topBarChipClass() {
  return "rounded-full border border-white/10 bg-white/[0.06] px-3 py-1 text-xs font-medium text-white/70";
}

function topBarButtonClass(active = false) {
  const base = "inline-flex h-8 items-center gap-1.5 rounded-lg px-3 text-xs font-medium transition disabled:pointer-events-none disabled:opacity-35 focus:outline-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30";
  return active ? `${base} bg-white text-black hover:bg-white hover:text-black` : `${base} text-white/75 hover:bg-white/10 hover:text-white`;
}

export default App;
