import { defineStore, acceptHMRUpdate } from 'pinia';
import {
  getSearchProvider,
  getThemePreset,
  iconDensityRange,
  iconRadiusRange,
  layoutDensityPresets,
  searchProviders,
  themePresets,
  type SearchProviderId,
  type ThemePresetId,
} from '@/config/settingsPresets';

type IconDensity = number;
type LayoutDensity = 1 | 2 | 3 | 4;

type SettingsState = {
  showSearch: boolean;
  showClock: boolean;
  showDate: boolean;
  showSeconds: boolean;
  use24Hour: boolean;
  openInNewTab: boolean;
  searchProvider: SearchProviderId;
  showIconLabels: boolean;
  iconDensity: IconDensity;
  iconRadius: number;
  themeId: ThemePresetId;
  layoutDensity: LayoutDensity;
  autoAlign: boolean;
  compactSidebar: boolean;
  showGroupLabels: boolean;
};

const SETTINGS_STORAGE_KEY = 'itab_settings';

const defaultSettings: SettingsState = {
  showSearch: true,
  showClock: true,
  showDate: true,
  showSeconds: false,
  use24Hour: true,
  openInNewTab: true,
  searchProvider: getSearchProvider().id,
  showIconLabels: true,
  iconDensity: iconDensityRange.default,
  iconRadius: iconRadiusRange.default,
  themeId: getThemePreset().id,
  layoutDensity: 2,
  autoAlign: true,
  compactSidebar: false,
  showGroupLabels: true,
};

const searchProviderIds = new Set(searchProviders.map(item => item.id));
const themePresetIds = new Set(themePresets.map(item => item.id));
const layoutDensityValues = new Set(layoutDensityPresets.map(item => item.value));
const clampRange = (value: number, min: number, max: number) =>
  Math.min(Math.max(value, min), max);

const loadSettings = (): SettingsState => {
  const raw = localStorage.getItem(SETTINGS_STORAGE_KEY);
  if (!raw) return { ...defaultSettings };
  try {
    const parsed = JSON.parse(raw) as Partial<SettingsState> | null;
    if (!parsed || typeof parsed !== 'object') {
      return { ...defaultSettings };
    }
    return {
      showSearch: typeof parsed.showSearch === 'boolean' ? parsed.showSearch : defaultSettings.showSearch,
      showClock: typeof parsed.showClock === 'boolean' ? parsed.showClock : defaultSettings.showClock,
      showDate: typeof parsed.showDate === 'boolean' ? parsed.showDate : defaultSettings.showDate,
      showSeconds: typeof parsed.showSeconds === 'boolean' ? parsed.showSeconds : defaultSettings.showSeconds,
      use24Hour: typeof parsed.use24Hour === 'boolean' ? parsed.use24Hour : defaultSettings.use24Hour,
      openInNewTab: typeof parsed.openInNewTab === 'boolean' ? parsed.openInNewTab : defaultSettings.openInNewTab,
      searchProvider:
        typeof parsed.searchProvider === 'string' && searchProviderIds.has(parsed.searchProvider)
          ? parsed.searchProvider
          : defaultSettings.searchProvider,
      showIconLabels:
        typeof parsed.showIconLabels === 'boolean' ? parsed.showIconLabels : defaultSettings.showIconLabels,
      iconDensity:
        typeof parsed.iconDensity === 'number'
          ? clampRange(parsed.iconDensity, iconDensityRange.min, iconDensityRange.max)
          : defaultSettings.iconDensity,
      iconRadius:
        typeof parsed.iconRadius === 'number'
          ? clampRange(parsed.iconRadius, iconRadiusRange.min, iconRadiusRange.max)
          : defaultSettings.iconRadius,
      themeId:
        typeof parsed.themeId === 'string' && themePresetIds.has(parsed.themeId)
          ? parsed.themeId
          : defaultSettings.themeId,
      layoutDensity:
        typeof parsed.layoutDensity === 'number' && layoutDensityValues.has(parsed.layoutDensity)
          ? parsed.layoutDensity
          : defaultSettings.layoutDensity,
      autoAlign: typeof parsed.autoAlign === 'boolean' ? parsed.autoAlign : defaultSettings.autoAlign,
      compactSidebar:
        typeof parsed.compactSidebar === 'boolean' ? parsed.compactSidebar : defaultSettings.compactSidebar,
      showGroupLabels:
        typeof parsed.showGroupLabels === 'boolean' ? parsed.showGroupLabels : defaultSettings.showGroupLabels,
    };
  } catch {
    return { ...defaultSettings };
  }
};

const persistSettings = (state: SettingsState) => {
  localStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(state));
};

export const useSettingsStore = defineStore('settings', {
  state: (): SettingsState => loadSettings(),
  actions: {
    setSetting<K extends keyof SettingsState>(key: K, value: SettingsState[K]) {
      this[key] = value;
      persistSettings(this.$state);
    },
    reset() {
      Object.assign(this.$state, defaultSettings);
      persistSettings(this.$state);
    },
  }
});

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useSettingsStore, import.meta.hot));
}
