import { defineStore } from 'pinia';
import type { BreakpointKey, ControlTab, ElementState } from '../core/types';
import { useDocumentStore } from './document';

export type PanelName = 'widgets' | 'settings' | 'global' | 'history' | 'page' | 'notes';
/** Optional action link rendered inside a toast (e.g. "Log in" after the session expired). Opens in a new tab. */
export interface ToastLink {
  href: string;
  label: string;
}

export interface DragState {
  kind: 'new' | 'move';
  /** widget type when kind === 'new' */
  type?: string;
  /** element id when kind === 'move' */
  id?: string;
  /** Initial settings of the new element (kind === 'new'), e.g. `component_id` of a component instance. */
  settings?: Record<string, unknown>;
  /** Label of the new element (navigator / toolbar name). */
  elementLabel?: string;
  label: string;
}

export interface DropTarget {
  parentId: string | null;
  index: number;
  /** Visual placement for the indicator */
  position: 'before' | 'after' | 'inside';
  targetId: string | null;
}

function readBool(key: string, fallback: boolean): boolean {
  try {
    const v = localStorage.getItem(key);
    return v === null ? fallback : v === '1';
  } catch {
    return fallback;
  }
}

function writeBool(key: string, value: boolean): void {
  try {
    localStorage.setItem(key, value ? '1' : '0');
  } catch {
    /* ignore */
  }
}

export const useEditorStore = defineStore('editor', {
  state: () => ({
    selectedId: null as string | null,
    hoveredId: null as string | null,
    breakpoint: 'desktop' as BreakpointKey,
    state: 'normal' as ElementState,
    panel: 'widgets' as PanelName,
    settingsTab: 'content' as ControlTab,
    navigatorOpen: readBool('zadex:navigator', false),
    darkMode: readBool('zadex:dark', typeof matchMedia !== 'undefined' && matchMedia('(prefers-color-scheme: dark)').matches),
    searchOpen: false,
    shortcutsOpen: false,
    previewMode: false,
    canvasReady: false,
    dragging: null as DragState | null,
    dropTarget: null as DropTarget | null,
    widgetSearch: '',
    /** Navigator expanded state per element id. */
    expanded: {} as Record<string, boolean>,
    /** Element currently being edited inline. */
    inlineEditingId: null as string | null,
    /** Widget type of the selected element (drives the "reset to Content tab on type change" rule). */
    selectedType: null as string | null,
    toast: null as { message: string; type: 'info' | 'success' | 'error'; id: number; link?: ToastLink } | null,
  }),

  getters: {
    hasSelection: (s) => s.selectedId !== null,
  },

  actions: {
    select(id: string | null): void {
      const prevType = this.selectedType;
      this.selectedId = id;
      if (id) {
        this.panel = 'settings';
        this.selectedType = useDocumentStore().get(id)?.type ?? null;
        // A different kind of element: start on its Content tab instead of a stale Style/Advanced tab.
        if (this.selectedType !== prevType) this.settingsTab = 'content';
      } else {
        this.selectedType = null;
        if (this.panel === 'settings') this.panel = 'widgets';
      }
    },
    hover(id: string | null): void {
      if (this.hoveredId !== id) this.hoveredId = id;
    },
    setBreakpoint(bp: BreakpointKey): void {
      this.breakpoint = bp;
    },
    setState(state: ElementState): void {
      this.state = state;
    },
    setPanel(panel: PanelName): void {
      this.panel = panel;
    },
    setTab(tab: ControlTab): void {
      this.settingsTab = tab;
    },
    toggleNavigator(force?: boolean): void {
      this.navigatorOpen = force ?? !this.navigatorOpen;
      writeBool('zadex:navigator', this.navigatorOpen);
    },
    toggleDark(force?: boolean): void {
      this.darkMode = force ?? !this.darkMode;
      writeBool('zadex:dark', this.darkMode);
    },
    togglePreview(force?: boolean): void {
      this.previewMode = force ?? !this.previewMode;
    },
    toggleSearch(force?: boolean): void {
      this.searchOpen = force ?? !this.searchOpen;
    },
    toggleShortcuts(force?: boolean): void {
      this.shortcutsOpen = force ?? !this.shortcutsOpen;
    },
    setExpanded(id: string, value: boolean): void {
      this.expanded[id] = value;
    },
    startDrag(drag: DragState): void {
      this.dragging = drag;
      this.dropTarget = null;
    },
    setDropTarget(target: DropTarget | null): void {
      this.dropTarget = target;
    },
    endDrag(): void {
      this.dragging = null;
      this.dropTarget = null;
    },
    notify(message: string, type: 'info' | 'success' | 'error' = 'info', link?: ToastLink): void {
      this.toast = { message, type, id: Date.now(), ...(link ? { link } : {}) };
    },
  },
});
