import { create } from "zustand";
import {
  defaultFavoriteSidebarItemIds,
  defaultMobileDockItemIds,
  getValidSidebarItemIds,
  navigationPresets,
  sidebarNavItemIds,
  type NavigationPresetId,
} from "@/lib/sidebar-navigation";

const SIDEBAR_ITEMS_STORAGE_KEY = "mindavio-sidebar-hidden-items";
const SIDEBAR_LAYOUT_STORAGE_KEY = "mindavio-sidebar-layout";

interface SidebarLayoutPreferences {
  favoriteIds: string[];
  hiddenIds: string[];
  customOrder: string[];
  mobileDockIds: string[];
}

interface UIState {
  sidebarOpen: boolean;
  sidebarCollapsed: boolean;
  hiddenSidebarItemIds: string[];
  favoriteSidebarItemIds: string[];
  sidebarCustomOrderIds: string[];
  mobileDockItemIds: string[];
  sidebarPreferencesLoaded: boolean;
  commandPaletteOpen: boolean;
  toggleSidebar: () => void;
  setSidebarOpen: (open: boolean) => void;
  toggleSidebarCollapsed: () => void;
  initSidebarPreferences: () => void;
  toggleSidebarItem: (itemId: string) => void;
  toggleFavoriteSidebarItem: (itemId: string) => void;
  toggleMobileDockItem: (itemId: string) => void;
  moveSidebarItem: (itemId: string, direction: "up" | "down") => void;
  applyNavigationPreset: (presetId: NavigationPresetId) => void;
  showAllSidebarItems: () => void;
  setCommandPaletteOpen: (open: boolean) => void;
}

function persistHiddenItems(hiddenItemIds: string[]) {
  if (typeof window === "undefined") return;
  localStorage.setItem(SIDEBAR_ITEMS_STORAGE_KEY, JSON.stringify(hiddenItemIds));
}

function persistLayoutPreferences(preferences: SidebarLayoutPreferences) {
  if (typeof window === "undefined") return;
  localStorage.setItem(SIDEBAR_LAYOUT_STORAGE_KEY, JSON.stringify(preferences));
  persistHiddenItems(preferences.hiddenIds);
}

function normalizeUniqueItemIds(itemIds: unknown, fallback: string[]) {
  if (!Array.isArray(itemIds)) return fallback;
  return Array.from(new Set(getValidSidebarItemIds(itemIds.filter((id): id is string => typeof id === "string"))));
}

function normalizeMobileDockIds(itemIds: unknown, fallback: string[]) {
  return normalizeUniqueItemIds(itemIds, fallback).slice(0, 5);
}

function buildLayoutPreferences(state: Pick<UIState, "favoriteSidebarItemIds" | "hiddenSidebarItemIds" | "sidebarCustomOrderIds" | "mobileDockItemIds">): SidebarLayoutPreferences {
  return {
    customOrder: state.sidebarCustomOrderIds,
    favoriteIds: state.favoriteSidebarItemIds,
    hiddenIds: state.hiddenSidebarItemIds,
    mobileDockIds: state.mobileDockItemIds,
  };
}

export const useUIStore = create<UIState>((set) => ({
  sidebarOpen: false,
  sidebarCollapsed: false,
  hiddenSidebarItemIds: [],
  favoriteSidebarItemIds: defaultFavoriteSidebarItemIds,
  sidebarCustomOrderIds: sidebarNavItemIds,
  mobileDockItemIds: defaultMobileDockItemIds,
  sidebarPreferencesLoaded: false,
  commandPaletteOpen: false,
  toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),
  setSidebarOpen: (open) => set({ sidebarOpen: open }),
  toggleSidebarCollapsed: () =>
    set((s) => ({ sidebarCollapsed: !s.sidebarCollapsed })),
  initSidebarPreferences: () => {
    if (typeof window === "undefined") return;

    try {
      const layoutStored = localStorage.getItem(SIDEBAR_LAYOUT_STORAGE_KEY);
      const layoutParsed = layoutStored ? (JSON.parse(layoutStored) as Partial<SidebarLayoutPreferences>) : null;
      const stored = localStorage.getItem(SIDEBAR_ITEMS_STORAGE_KEY);
      const parsed = stored ? (JSON.parse(stored) as unknown) : [];
      const hiddenSidebarItemIds = normalizeUniqueItemIds(
        layoutParsed?.hiddenIds ?? parsed,
        []
      );
      const favoriteSidebarItemIds = normalizeUniqueItemIds(
        layoutParsed?.favoriteIds,
        defaultFavoriteSidebarItemIds
      ).filter((id) => !hiddenSidebarItemIds.includes(id));
      const sidebarCustomOrderIds = [
        ...normalizeUniqueItemIds(layoutParsed?.customOrder, sidebarNavItemIds),
        ...sidebarNavItemIds,
      ].filter((id, index, arr) => arr.indexOf(id) === index);
      const mobileDockItemIds = normalizeMobileDockIds(
        layoutParsed?.mobileDockIds,
        defaultMobileDockItemIds
      ).filter((id) => !hiddenSidebarItemIds.includes(id));

      set({
        favoriteSidebarItemIds,
        hiddenSidebarItemIds,
        mobileDockItemIds,
        sidebarCustomOrderIds,
        sidebarPreferencesLoaded: true,
      });
    } catch {
      set({
        favoriteSidebarItemIds: defaultFavoriteSidebarItemIds,
        hiddenSidebarItemIds: [],
        mobileDockItemIds: defaultMobileDockItemIds,
        sidebarCustomOrderIds: sidebarNavItemIds,
        sidebarPreferencesLoaded: true,
      });
    }
  },
  toggleSidebarItem: (itemId) =>
    set((state) => {
      const hiddenSidebarItemIds = state.hiddenSidebarItemIds.includes(itemId)
        ? state.hiddenSidebarItemIds.filter((id) => id !== itemId)
        : [...state.hiddenSidebarItemIds, itemId];
      const favoriteSidebarItemIds = state.favoriteSidebarItemIds.filter((id) => !hiddenSidebarItemIds.includes(id));
      const mobileDockItemIds = state.mobileDockItemIds.filter((id) => !hiddenSidebarItemIds.includes(id));
      const nextState = {
        favoriteSidebarItemIds,
        hiddenSidebarItemIds,
        mobileDockItemIds,
        sidebarCustomOrderIds: state.sidebarCustomOrderIds,
      };

      persistLayoutPreferences(buildLayoutPreferences(nextState));
      return nextState;
    }),
  toggleFavoriteSidebarItem: (itemId) =>
    set((state) => {
      if (state.hiddenSidebarItemIds.includes(itemId)) return {};
      const favoriteSidebarItemIds = state.favoriteSidebarItemIds.includes(itemId)
        ? state.favoriteSidebarItemIds.filter((id) => id !== itemId)
        : [...state.favoriteSidebarItemIds, itemId];
      const nextState = {
        favoriteSidebarItemIds,
        hiddenSidebarItemIds: state.hiddenSidebarItemIds,
        mobileDockItemIds: state.mobileDockItemIds,
        sidebarCustomOrderIds: state.sidebarCustomOrderIds,
      };

      persistLayoutPreferences(buildLayoutPreferences(nextState));
      return { favoriteSidebarItemIds };
    }),
  toggleMobileDockItem: (itemId) =>
    set((state) => {
      if (state.hiddenSidebarItemIds.includes(itemId)) return {};
      const exists = state.mobileDockItemIds.includes(itemId);
      const mobileDockItemIds = exists
        ? state.mobileDockItemIds.filter((id) => id !== itemId)
        : [...state.mobileDockItemIds, itemId].slice(0, 5);
      const nextState = {
        favoriteSidebarItemIds: state.favoriteSidebarItemIds,
        hiddenSidebarItemIds: state.hiddenSidebarItemIds,
        mobileDockItemIds,
        sidebarCustomOrderIds: state.sidebarCustomOrderIds,
      };

      persistLayoutPreferences(buildLayoutPreferences(nextState));
      return { mobileDockItemIds };
    }),
  moveSidebarItem: (itemId, direction) =>
    set((state) => {
      const sidebarCustomOrderIds = [
        ...state.sidebarCustomOrderIds,
        ...sidebarNavItemIds,
      ].filter((id, index, arr) => arr.indexOf(id) === index);
      const currentIndex = sidebarCustomOrderIds.indexOf(itemId);
      if (currentIndex === -1) return {};
      const nextIndex = direction === "up" ? currentIndex - 1 : currentIndex + 1;
      if (nextIndex < 0 || nextIndex >= sidebarCustomOrderIds.length) return {};
      const nextOrder = [...sidebarCustomOrderIds];
      [nextOrder[currentIndex], nextOrder[nextIndex]] = [nextOrder[nextIndex], nextOrder[currentIndex]];
      const nextState = {
        favoriteSidebarItemIds: state.favoriteSidebarItemIds,
        hiddenSidebarItemIds: state.hiddenSidebarItemIds,
        mobileDockItemIds: state.mobileDockItemIds,
        sidebarCustomOrderIds: nextOrder,
      };

      persistLayoutPreferences(buildLayoutPreferences(nextState));
      return { sidebarCustomOrderIds: nextOrder };
    }),
  applyNavigationPreset: (presetId) =>
    set(() => {
      const preset = navigationPresets.find((item) => item.id === presetId);
      if (!preset) return {};
      const nextState = {
        favoriteSidebarItemIds: getValidSidebarItemIds(preset.favoriteIds),
        hiddenSidebarItemIds: getValidSidebarItemIds(preset.hiddenIds),
        mobileDockItemIds: getValidSidebarItemIds(preset.mobileDockIds).slice(0, 5),
        sidebarCustomOrderIds: [
          ...preset.favoriteIds,
          ...sidebarNavItemIds,
        ].filter((id, index, arr) => sidebarNavItemIds.includes(id) && arr.indexOf(id) === index),
      };

      persistLayoutPreferences(buildLayoutPreferences(nextState));
      return nextState;
    }),
  showAllSidebarItems: () =>
    set((state) => {
      const nextState = {
        favoriteSidebarItemIds: state.favoriteSidebarItemIds,
        hiddenSidebarItemIds: [],
        mobileDockItemIds: state.mobileDockItemIds,
        sidebarCustomOrderIds: state.sidebarCustomOrderIds,
      };

      persistLayoutPreferences(buildLayoutPreferences(nextState));
      return { hiddenSidebarItemIds: [] };
    }),
  setCommandPaletteOpen: (open) => set({ commandPaletteOpen: open }),
}));
