import { computed, ref } from 'vue';
import { useDebounceFn } from '@vueuse/core';
import { type WorkbenchModuleKey, useWorkbenchModules } from './use-workbench-modules';
import { buildDefaultLayout } from './workbench-layout-default';
import type { LayoutStorage } from './layout-storage';
import { LocalStorageAdapter } from './layout-storage-local';
import { reconcileLayout } from './workbench-layout-reconcile';
import { WORKBENCH_LAYOUT_VERSION, type WorkbenchGridItem, type WorkbenchLayout } from './workbench-layout-types';

export type WorkbenchMode = 'normal' | 'editing';

interface UseWorkbenchLayoutOptions {
  userId: string;
  storage?: LayoutStorage;
}

export function useWorkbenchLayout(options: UseWorkbenchLayoutOptions) {
  const { getAllModules } = useWorkbenchModules();
  const storage = options.storage ?? new LocalStorageAdapter();

  const layout = ref<WorkbenchLayout>(buildDefaultLayout(getAllModules()));
  const mode = ref<WorkbenchMode>('normal');
  const dirty = ref(false);
  const saving = ref(false);
  const error = ref<Error | null>(null);

  let snapshotBeforeEdit: WorkbenchLayout | null = null;

  async function load() {
    const fromStorage = await storage.load(options.userId);
    if (fromStorage && fromStorage.version === WORKBENCH_LAYOUT_VERSION) {
      layout.value = reconcileLayout(fromStorage, getAllModules());
      return;
    }
    // 版本不匹配 / 无存储：走新默认布局；旧 settings 迁移过来，避免用户偏好（如 shortcut.menuKeys）被 version bump 清空
    const fresh = buildDefaultLayout(getAllModules());
    if (fromStorage?.settings) {
      fresh.settings = { ...fromStorage.settings };
    }
    layout.value = fresh;
  }

  const persist = useDebounceFn(async () => {
    saving.value = true;
    error.value = null;
    try {
      await storage.save(options.userId, layout.value);
    } catch (err) {
      error.value = err as Error;
    } finally {
      saving.value = false;
    }
  }, 500);

  function markDirty() {
    if (mode.value === 'editing') {
      dirty.value = true;
    } else {
      // 非编辑态写直接落盘
      persist();
    }
  }

  function enterEditing() {
    snapshotBeforeEdit = JSON.parse(JSON.stringify(layout.value));
    mode.value = 'editing';
    dirty.value = false;
  }

  async function saveEditing() {
    saving.value = true;
    try {
      await storage.save(options.userId, layout.value);
      mode.value = 'normal';
      dirty.value = false;
      snapshotBeforeEdit = null;
    } catch (err) {
      error.value = err as Error;
    } finally {
      saving.value = false;
    }
  }

  function cancelEditing() {
    if (snapshotBeforeEdit) {
      layout.value = snapshotBeforeEdit;
    }
    mode.value = 'normal';
    dirty.value = false;
    snapshotBeforeEdit = null;
  }

  function hideModule(key: WorkbenchModuleKey) {
    layout.value.grid = layout.value.grid.filter(item => item.i !== key);
    if (!layout.value.hidden.includes(key)) layout.value.hidden.push(key);
    markDirty();
  }

  function showModule(key: WorkbenchModuleKey) {
    if (layout.value.grid.some(item => item.i === key)) return;
    layout.value.hidden = layout.value.hidden.filter(k => k !== key);
    const meta = getAllModules().find(m => m.key === key);
    if (!meta) return;
    const nextY = layout.value.grid.reduce((max, g) => Math.max(max, g.y + g.h), 0);
    layout.value.grid.push({
      i: key,
      x: meta.defaultGrid.x,
      y: nextY,
      w: meta.defaultGrid.w,
      h: meta.defaultGrid.h,
      minW: meta.defaultGrid.minW,
      minH: meta.defaultGrid.minH
    });
    markDirty();
  }

  function updateGrid(grid: WorkbenchGridItem[]) {
    layout.value.grid = grid;
    markDirty();
  }

  function updateModuleSettings<K extends keyof WorkbenchLayout['settings']>(
    key: K,
    value: WorkbenchLayout['settings'][K]
  ) {
    layout.value.settings = { ...layout.value.settings, [key]: value };
    markDirty();
  }

  async function resetToDefault() {
    const fresh = buildDefaultLayout(getAllModules());
    // 重置只针对布局（位置/尺寸/显隐）；用户偏好（如 shortcut.menuKeys）原样保留
    fresh.settings = { ...layout.value.settings };
    layout.value = fresh;
    mode.value = 'normal';
    dirty.value = false;
    snapshotBeforeEdit = null;
    await storage.save(options.userId, layout.value);
  }

  const hiddenMetas = computed(() => {
    const allMeta = getAllModules();
    return layout.value.hidden
      .map(k => allMeta.find(m => m.key === k))
      .filter((m): m is NonNullable<typeof m> => Boolean(m));
  });

  return {
    layout,
    mode,
    dirty,
    saving,
    error,
    hiddenMetas,
    load,
    enterEditing,
    saveEditing,
    cancelEditing,
    hideModule,
    showModule,
    updateGrid,
    updateModuleSettings,
    resetToDefault
  };
}
