import { useEffect, useRef, useCallback, useState } from "react";
import * as Tabs from "@radix-ui/react-tabs";
import * as Dialog from "@radix-ui/react-dialog";
import * as Switch from "@radix-ui/react-switch";
import { Cross2Icon, ChevronLeftIcon, ChevronRightIcon, RocketIcon } from "@radix-ui/react-icons";
import type { Stage as StageType } from "konva/lib/Stage";
import { CanvasEditor } from "@/components/Canvas";
import { ExtensionSlot } from "@/components/Slots/ExtensionSlot";
import "@/extensions/registry";
import { registerProExtensions } from "@/extensions/registerPro";
import { ElementToolbar } from "@/components/Toolbar";
import { SettingsPanel, FloatingSettingsPanel, ContainerSettingsPanel } from "@/components/Settings";
import { LayerTree } from "@/components/Tree/LayerTree";
import { LayoutsPanel } from "@/components/Tree/LayoutsPanel";
import { PresetsPanel } from "@/components/Presets";
import { ExportModal } from "@/components/Export/ExportModal";
import { OnboardingGuide } from "@/components/Onboarding";
import { UpgradeButton } from "@/components/Pro";
import { createElement } from "@/registry";
import type { ElementDefinition, PresetDefinition } from "@/registry";
import { isPro } from "@/utils/license";
import {
  useCanvasStore,
  useElements,
  useSelectedElements,
  useActiveScenario,
  useSettingsMode,
  useContainerSelected,
} from "@/stores/canvasStore";
import { useLayoutPersistStore, hasAnyActiveLocation } from "@/stores/layoutPersistStore";
import { useOnboardingStore } from "@/stores/onboardingStore";
import { useCanvas } from "@/hooks/useCanvas";
import { useCreateLayout, useUpdateLayout, useLayouts, useLocations } from "@/hooks/useLayouts";
import { useUpdateFontsOnSave } from "@/hooks/useSettings";
import { useToast } from "@/hooks/useToast";
import { usePreloadAllGoogleFonts } from "@/hooks/useGoogleFonts";
import { extractGoogleFontsWithVariants } from "@/utils/fontUtils";
import { getErrorMessage } from "@/utils/errorMessage";
import type { PriceScenario, CanvasState, LayoutTemplate } from "@/types";
import { getLocationsMap } from "@/types";

const scenarioLabels: Record<PriceScenario, string> = {
  simple: "Simple Price",
  sale: "Sale Price",
  variable_simple: "Variable Price",
  variable_sale: "Variable Sale",
};

function App() {
  const stageRef = useRef<StageType>(null);
  const canvasContainerRef = useRef<HTMLDivElement>(null);
  const sidebarRef = useRef<HTMLElement>(null);
  const [saveDialogOpen, setSaveDialogOpen] = useState(false);
  const [exportModalOpen, setExportModalOpen] = useState(false);
  const [layoutName, setLayoutName] = useState("");
  const [currentLayoutId, setCurrentLayoutId] = useState<number | null>(null);
  const [isSaving, setIsSaving] = useState(false);
  const [activeLocations, setActiveLocations] = useState<Record<string, boolean>>({});
  const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
  // Flag to prevent auto-loading when intentionally starting fresh
  const skipAutoLoad = useRef(false);

  // Preload all Google fonts on app initialization
  usePreloadAllGoogleFonts();
  const updateFontsOnSave = useUpdateFontsOnSave();
  const toast = useToast();

  const syncLocalFontsFromLayout = useCallback(
    (canvasData?: CanvasState) => {
      if (!canvasData?.elements?.length) {
        return;
      }

      const fonts = extractGoogleFontsWithVariants(canvasData.elements);
      void updateFontsOnSave(fonts);
    },
    [updateFontsOnSave],
  );

  useEffect(() => {
    registerProExtensions();
  }, []);

  // Settings panel mode from store
  const settingsMode = useSettingsMode();
  const toggleSettingsMode = useCanvasStore((state) => state.toggleSettingsMode);
  const containerSelected = useContainerSelected();

  // Onboarding state
  const onboardingCompleted = useOnboardingStore((state) => state.completed);
  const startOnboarding = useOnboardingStore((state) => state.startOnboarding);

  const activeScenario = useActiveScenario();
  const elements = useElements();
  const selectedElements = useSelectedElements();
  const setActiveScenario = useCanvasStore((state) => state.setActiveScenario);
  const loadCanvasState = useCanvasStore((state) => state.loadCanvasState);
  const clearCanvas = useCanvasStore((state) => state.clearCanvas);
  const { handleKeyDown, deleteSelected } = useCanvas({ stageRef });

  // Layout persistence
  const setLastSelectedLayout = useLayoutPersistStore((state) => state.setLastSelectedLayout);
  const getLastSelectedLayout = useLayoutPersistStore((state) => state.getLastSelectedLayout);
  const setStoreCurrentLayoutId = useLayoutPersistStore((state) => state.setCurrentLayoutId);

  useEffect(() => {
    setStoreCurrentLayoutId(currentLayoutId);
  }, [currentLayoutId, setStoreCurrentLayoutId]);

  // Fetch available locations from API (for backward compatibility)
  // Primary source is now oppbAdmin.locations from PHP
  const { data: apiLocations } = useLocations();
  // Use PHP-provided locations (via getLocationsMap), fallback to API response
  const locations = apiLocations && Object.keys(apiLocations).length > 0 ? apiLocations : getLocationsMap();

  // Fetch layouts for active scenario
  const { data: layoutsData, isLoading: isLoadingLayouts } = useLayouts({
    scenario: activeScenario,
    perPage: 50,
  });

  // Debug logging
  useEffect(() => {
    console.log("[PBO] oppbAdmin:", window.oppbAdmin);
    console.log("[PBO] layouts:", layoutsData);
    console.log("[PBO] isLoadingLayouts:", isLoadingLayouts);
  }, [layoutsData, isLoadingLayouts]);

  // Helper to load a layout into canvas
  const loadLayout = useCallback(
    (layout: LayoutTemplate) => {
      setCurrentLayoutId(layout.id);
      setLayoutName(layout.name);
      setActiveLocations(layout.activeLocations || {});
      if (layout.canvasData) {
        loadCanvasState(layout.canvasData as Partial<CanvasState>);
      }
      // Persist selection to localStorage using layout's scenario (not activeScenario)
      // This ensures correct persistence even during scenario transitions
      setLastSelectedLayout(layout.scenario, layout.id);
    },
    [loadCanvasState, setLastSelectedLayout],
  );

  // Auto-load layout when layouts data changes (after scenario change or initial load)
  useEffect(() => {
    // Skip if layouts are still loading or we already have a layout loaded
    if (isLoadingLayouts || currentLayoutId !== null) return;

    // Skip auto-load if we intentionally started fresh (preset/new layout)
    if (skipAutoLoad.current) {
      skipAutoLoad.current = false;
      return;
    }

    const layouts = layoutsData?.data;
    if (!layouts || layouts.length === 0) return;

    // Make sure layouts belong to current scenario (avoid race condition with stale data)
    const firstLayout = layouts[0];
    if (firstLayout && firstLayout.scenario !== activeScenario) {
      console.log("[PBO] Skipping auto-load - layouts are for different scenario");
      return;
    }

    // First try to load the last selected layout for this scenario
    const lastSelectedId = getLastSelectedLayout(activeScenario);
    if (lastSelectedId !== null) {
      const lastLayout = layouts.find((l) => l.id === lastSelectedId);
      if (lastLayout) {
        console.log("[PBO] Auto-loading last selected layout:", lastLayout.name);
        loadLayout(lastLayout);
        return;
      }
    }

    // Fallback: find first layout with any active location
    const layoutWithActiveLocation = layouts.find((layout) => hasAnyActiveLocation(layout.activeLocations));

    if (layoutWithActiveLocation) {
      console.log("[PBO] Auto-loading first layout with active location:", layoutWithActiveLocation.name);
      loadLayout(layoutWithActiveLocation);
    }
  }, [layoutsData, isLoadingLayouts, currentLayoutId, activeScenario, getLastSelectedLayout, loadLayout]);

  // Load layout when scenario changes
  const handleScenarioChange = useCallback(
    (scenario: PriceScenario) => {
      setActiveScenario(scenario);
      // Clear current layout when switching scenarios
      // The auto-load useEffect will handle loading the appropriate layout
      setCurrentLayoutId(null);
      setLayoutName("");
      setActiveLocations({});
      clearCanvas();
    },
    [setActiveScenario, clearCanvas],
  );

  // Initialize default locations on mount
  useEffect(() => {
    const defaultLocs: Record<string, boolean> = {};
    Object.keys(locations).forEach((loc) => {
      defaultLocs[loc] = false;
    });
    setActiveLocations(defaultLocs);
  }, [locations]);

  // Mutations
  const createLayout = useCreateLayout({
    onSuccess: (layout) => {
      setCurrentLayoutId(layout.id);
      setLastSelectedLayout(activeScenario, layout.id);
      setSaveDialogOpen(false);
      setIsSaving(false);
      syncLocalFontsFromLayout(layout.canvasData);
      toast.success("Layout saved", { description: `"${layout.name}" was created successfully.` });
    },
    onError: (error) => {
      setIsSaving(false);
      toast.error("Failed to save layout", { description: getErrorMessage(error) });
    },
  });

  const updateLayout = useUpdateLayout({
    onSuccess: (layout) => {
      setSaveDialogOpen(false);
      setIsSaving(false);
      syncLocalFontsFromLayout(layout.canvasData);
      toast.success("Layout saved", { description: `"${layout.name}" was updated successfully.` });
    },
    onError: (error) => {
      setIsSaving(false);
      toast.error("Failed to save layout", { description: getErrorMessage(error) });
    },
  });

  // Handle adding element from toolbar
  const handleAddElement = useCallback((definition: ElementDefinition) => {
    const newElement = createElement(definition.type);
    useCanvasStore.getState().addElementDirect(newElement);
  }, []);

  // Handle adding element from onboarding (adds regularPrice)
  const handleOnboardingAddElement = useCallback(() => {
    const newElement = createElement("regularPrice");
    useCanvasStore.getState().addElementDirect(newElement);
    // Select the element to show settings panel
    useCanvasStore.getState().selectElement(newElement.id);
  }, []);

  // Handle applying a preset - clears canvas and adds preset elements
  const handleApplyPreset = useCallback(
    (preset: PresetDefinition) => {
      // Set flag to prevent auto-loading when we clear the layout ID
      skipAutoLoad.current = true;

      // Clear existing canvas
      clearCanvas();

      // Reset layout info since we're starting fresh
      setCurrentLayoutId(null);
      setLayoutName("");
      const defaultLocs: Record<string, boolean> = {};
      Object.keys(locations).forEach((loc) => {
        defaultLocs[loc] = false;
      });
      setActiveLocations(defaultLocs);

      // Add each element from the preset
      const store = useCanvasStore.getState();
      preset.elements.forEach((elementOverrides) => {
        if (elementOverrides.type) {
          const newElement = createElement(elementOverrides.type, elementOverrides);
          store.addElementDirect(newElement);
        }
      });

      // Apply container settings if provided
      if (preset.containerSettings) {
        store.updateContainerSettings(preset.containerSettings);
      }

      useCanvasStore.setState({ presetId: preset.id });
    },
    [clearCanvas, locations],
  );

  // Handle editing a layout from LayoutsPanel
  const handleEditLayout = useCallback(
    (layout: LayoutTemplate) => {
      loadLayout(layout);
    },
    [loadLayout],
  );

  // Handle creating a new layout from LayoutsPanel
  const handleNewLayout = useCallback(() => {
    // Set flag to prevent auto-loading when we clear the layout ID
    skipAutoLoad.current = true;

    setCurrentLayoutId(null);
    setLayoutName("");
    // Reset locations to all false
    const defaultLocs: Record<string, boolean> = {};
    Object.keys(locations).forEach((loc) => {
      defaultLocs[loc] = false;
    });
    setActiveLocations(defaultLocs);
    clearCanvas();
  }, [clearCanvas, locations]);

  // Handle save
  const handleSave = useCallback(() => {
    if (!layoutName.trim()) return;

    setIsSaving(true);
    const canvasState = useCanvasStore.getState();
    const canvasData = {
      elements: canvasState.elements,
      selectedIds: [],
      hoveredId: null,
      containerSelected: false,
      containerSettings: canvasState.containerSettings,
      zoom: canvasState.zoom,
      pan: canvasState.pan,
      showGrid: canvasState.showGrid,
      showGuides: canvasState.showGuides,
      snapToGuides: canvasState.snapToGuides,
      snapThreshold: canvasState.snapThreshold,
      activeGuides: [],
      showContainerBounds: canvasState.showContainerBounds,
      presetId: canvasState.presetId ?? null,
    };

    if (currentLayoutId) {
      updateLayout.mutate({
        id: currentLayoutId,
        name: layoutName,
        scenario: activeScenario,
        canvasData,
        activeLocations,
      });
    } else {
      createLayout.mutate({
        name: layoutName,
        scenario: activeScenario,
        canvasData,
        activeLocations,
      });
    }
  }, [layoutName, currentLayoutId, activeScenario, createLayout, updateLayout, activeLocations]);

  // Handle quick save (if already has ID)
  const handleQuickSave = useCallback(() => {
    if (currentLayoutId) {
      setIsSaving(true);
      const canvasState = useCanvasStore.getState();
      updateLayout.mutate({
        id: currentLayoutId,
        scenario: activeScenario,
        canvasData: {
          elements: canvasState.elements,
          selectedIds: [],
          hoveredId: null,
          containerSelected: false,
          containerSettings: canvasState.containerSettings,
          zoom: canvasState.zoom,
          pan: canvasState.pan,
          showGrid: canvasState.showGrid,
          showGuides: canvasState.showGuides,
          snapToGuides: canvasState.snapToGuides,
          snapThreshold: canvasState.snapThreshold,
          activeGuides: [],
          showContainerBounds: canvasState.showContainerBounds,
          presetId: canvasState.presetId ?? null,
        },
      });
    } else {
      setSaveDialogOpen(true);
    }
  }, [currentLayoutId, activeScenario, updateLayout]);

  // Keyboard shortcuts
  useEffect(() => {
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [handleKeyDown]);

  return (
    <div className="oppb-app-wrapper min-h-screen bg-canvas-bg">
      {/* Scenario Tabs */}
      <Tabs.Root
        value={activeScenario}
        onValueChange={(value) => handleScenarioChange(value as PriceScenario)}
        className="flex flex-col h-screen"
      >
        <header className="bg-surface border-b border-border px-4">
          <Tabs.List className="flex gap-1 h-[--size-toolbar-height] items-center">
            {(Object.keys(scenarioLabels) as PriceScenario[]).map((scenario) => (
              <Tabs.Trigger
                key={scenario}
                value={scenario}
                className="px-4 py-2 text-sm font-medium text-text-muted rounded-t-md transition-colors
                           data-[state=active]:text-primary data-[state=active]:bg-primary/10
                           hover:text-text hover:bg-surface-secondary cursor-pointer"
                disabled={isLoadingLayouts}
              >
                {scenarioLabels[scenario]}
              </Tabs.Trigger>
            ))}
            {isLoadingLayouts && <span className="ml-2 text-xs text-text-muted">Loading...</span>}
          </Tabs.List>
        </header>

        {/* Main Layout */}
        <div className="flex flex-1 overflow-hidden">
          {/* Left Sidebar - Presets, Layouts and Layer Tree */}
          <aside
            ref={sidebarRef}
            className={`oppb-sidebar-left bg-surface border-r border-border ${sidebarCollapsed ? "oppb-sidebar-left--collapsed" : ""}`}
          >
            {/* Sidebar Toggle Button */}
            <button
              type="button"
              className="oppb-sidebar-toggle"
              onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
              aria-label={sidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"}
            >
              <span className="oppb-sidebar-toggle__content">
                {sidebarCollapsed ? (
                  <ChevronRightIcon className="oppb-sidebar-toggle__icon w-4 h-4" />
                ) : (
                  <>
                    <ChevronLeftIcon className="oppb-sidebar-toggle__icon w-4 h-4" />
                    <span className="oppb-sidebar-toggle__label">Collapse</span>
                  </>
                )}
              </span>
            </button>

            {/* Sidebar Content */}
            <div className="oppb-sidebar-content overflow-y-auto">
              <div className="oppb-sidebar-presets" data-onboarding="presets">
                <PresetsPanel scenario={activeScenario} onApplyPreset={handleApplyPreset} />
              </div>
              <div className="oppb-sidebar-layouts" data-onboarding="layouts">
                <LayoutsPanel
                  scenario={activeScenario}
                  currentLayoutId={currentLayoutId}
                  onEditLayout={handleEditLayout}
                  onNewLayout={handleNewLayout}
                />
              </div>
              <div className="oppb-sidebar-layers" data-onboarding="layers">
                <LayerTree />
              </div>
            </div>
          </aside>

          {/* Center - Canvas Area */}
          <main className="flex-1 flex flex-col overflow-hidden">
            {/* Element Toolbar */}
            <div data-onboarding="toolbar">
              <ElementToolbar scenario={activeScenario} onAddElement={handleAddElement} />
            </div>

            {/* Canvas Actions Bar */}
            <div className="h-12 bg-surface border-b border-border px-4 flex items-center justify-between">
              <div className="flex items-center gap-4">
                <span className="text-xs text-text-muted">Zoom: {Math.round(useCanvasStore.getState().zoom * 100)}%</span>
                <ExtensionSlot name="canvas-toolbar" />
              </div>

              {/* Canvas controls */}
              {selectedElements.length > 0 && (
                <button className="oppb-button-ghost text-xs text-danger" onClick={deleteSelected}>
                  Delete Selected ({selectedElements.length})
                </button>
              )}
            </div>

            {/* Canvas */}
            <div ref={canvasContainerRef} className="flex-1 p-[--spacing-canvas] overflow-auto relative">
              <CanvasEditor />

              {/* Floating Settings Panel */}
              {settingsMode === "floating" && (
                <>
                  {containerSelected ? (
                    <ContainerSettingsPanel position={{ x: 100, y: 60 }} />
                  ) : (
                    <FloatingSettingsPanel containerRef={canvasContainerRef} />
                  )}
                </>
              )}
            </div>
          </main>

          {/* Right Sidebar - Settings (only when not in floating mode) */}
          {settingsMode === "sidebar" && (
            <aside className="bg-surface border-l border-border overflow-y-auto">
              <SettingsPanel />
            </aside>
          )}
        </div>

        {/* Footer */}
        <footer className="h-12 bg-surface border-t border-border px-4 flex items-center justify-between">
          <div className="flex items-center gap-4">
            <span className="text-xs text-text-muted">
              Opus Price Builder v1.0.0 | {elements.length} element(s)
              {currentLayoutId && ` | Layout #${currentLayoutId}`}
            </span>
            {/* Settings mode toggle */}
            <label className="flex items-center gap-2 cursor-pointer">
              <span className="text-xs text-text-muted">Sidebar</span>
              <Switch.Root
                checked={settingsMode === "sidebar"}
                onCheckedChange={toggleSettingsMode}
                className="w-8 h-4 bg-border rounded-full relative data-[state=checked]:bg-primary transition-colors"
              >
                <Switch.Thumb className="block w-3 h-3 bg-white rounded-full transition-transform translate-x-0.5 data-[state=checked]:translate-x-[18px]" />
              </Switch.Root>
            </label>
            {/* Start Tour button (only if tour was completed) */}
            {onboardingCompleted && (
              <button type="button" className="oppb-onboarding-start-btn" onClick={startOnboarding}>
                <RocketIcon className="w-3.5 h-3.5" />
                <span>Start Tour</span>
              </button>
            )}
          </div>
          <div className="flex gap-2 items-center">
            {/* Upgrade to Pro button (only for free users) */}
            {!isPro() && <UpgradeButton size="sm" />}
            {/* <button
              className="oppb-button-secondary text-xs flex items-center gap-1.5"
              onClick={() => {
                useCanvasStore.getState().clearSelection();
                setExportModalOpen(true);
              }}
            >
              <Share1Icon className="w-3.5 h-3.5" />
              Export
            </button>
            <button className="oppb-button-secondary text-xs">Preview</button> */}
            <button
              className="oppb-button-primary text-xs cursor-pointer"
              onClick={() => {
                useCanvasStore.getState().clearSelection();
                handleQuickSave();
              }}
              disabled={isSaving}
            >
              {isSaving ? "Saving..." : currentLayoutId ? "Save" : "Save Layout"}
            </button>
          </div>
        </footer>
      </Tabs.Root>

      {/* Onboarding Guide */}
      <OnboardingGuide onAddElement={handleOnboardingAddElement} />

      {/* Save Dialog */}
      <Dialog.Root open={saveDialogOpen} onOpenChange={setSaveDialogOpen}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-surface rounded-lg shadow-xl p-6 w-[400px] z-50">
            <Dialog.Title className="text-lg font-semibold text-text mb-4">Save Layout</Dialog.Title>

            <div className="space-y-4">
              <div>
                <label className="oppb-label block mb-1">Layout Name</label>
                <input
                  type="text"
                  className="oppb-input w-full"
                  placeholder="Enter layout name..."
                  value={layoutName}
                  onChange={(e) => setLayoutName(e.target.value)}
                  autoFocus
                />
              </div>

              <div>
                <label className="oppb-label block mb-1">Scenario</label>
                <input type="text" className="oppb-input w-full bg-surface-secondary" value={scenarioLabels[activeScenario]} disabled />
              </div>

              <div className="space-y-2">
                <label className="oppb-label block mb-2">Activate for locations</label>
                <p className="text-xs text-text-muted mb-3">
                  Enable this layout for specific display locations. Only one layout can be active per location.
                </p>
                <div className="space-y-2">
                  {Object.entries(locations).map(([locationKey, locationLabel]) => (
                    <label
                      key={locationKey}
                      className="flex items-center justify-between p-2 rounded-md bg-surface-secondary cursor-pointer hover:bg-surface-secondary/80"
                    >
                      <span className="text-sm text-text">{locationLabel}</span>
                      <Switch.Root
                        className="w-9 h-5 bg-border rounded-full relative data-[state=checked]:bg-primary outline-none"
                        checked={activeLocations[locationKey] || false}
                        onCheckedChange={(checked) =>
                          setActiveLocations((prev) => ({
                            ...prev,
                            [locationKey]: checked,
                          }))
                        }
                      >
                        <Switch.Thumb className="block w-4 h-4 bg-white rounded-full transition-transform duration-100 translate-x-0.5 will-change-transform data-[state=checked]:translate-x-4" />
                      </Switch.Root>
                    </label>
                  ))}
                </div>
              </div>
            </div>

            <div className="flex justify-end gap-2 mt-6">
              <Dialog.Close asChild>
                <button className="oppb-button-secondary text-sm">Cancel</button>
              </Dialog.Close>
              <button className="oppb-button-primary text-sm" onClick={handleSave} disabled={!layoutName.trim() || isSaving}>
                {isSaving ? "Saving..." : "Save"}
              </button>
            </div>

            <Dialog.Close asChild>
              <button className="absolute top-4 right-4 text-text-muted hover:text-text" aria-label="Close">
                <Cross2Icon className="w-4 h-4" />
              </button>
            </Dialog.Close>
          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

      {/* Export Modal */}
      <ExportModal open={exportModalOpen} onOpenChange={setExportModalOpen} />
    </div>
  );
}

export default App;
