// libs/setting/src/lib/store.ts

import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
import {
  BaseState,
  BaseActions,
  createInitializer,
  handleError,
  ApplicationStatus,
} from '@bc-game/core';
import {
  Theme,
  Language,
  SettingConfig,
  DEFAULT_SETTING_CONFIG,
  DEFAULT_SETTING_STATE,
} from './types';

// --- 스토어의 상태(State)와 액션(Actions) 인터페이스 정의 ---
interface SettingStoreState extends BaseState {
  status: ApplicationStatus;
  theme: Theme;
  language: Language;
  config: SettingConfig;
  _isSettingUp: boolean;
  _isTearingDown: boolean;
}

interface SettingStoreActions extends BaseActions {
  setup: (config?: Partial<SettingConfig>) => Promise<void>;
  teardown: () => Promise<void>;
  setTheme: (theme: Theme) => void;
  toggleTheme: () => void;
  setLanguage: (language: Language) => void;
  resetToDefaults: () => void;
}

export type SettingStore = SettingStoreState & SettingStoreActions;

// ===== Helper Functions =====

/**
 * 시스템 테마 감지
 */
const detectSystemTheme = (): Theme => {
  if (typeof window === 'undefined') return 'dark';
  return window.matchMedia('(prefers-color-scheme: dark)').matches
    ? 'dark'
    : 'light';
};

/**
 * 로컬 스토리지에서 테마 로드
 */
const loadThemeFromStorage = (storageKey: string): Theme | null => {
  if (typeof localStorage === 'undefined') return null;
  const stored = localStorage.getItem(`${storageKey}-theme`);
  if (stored === 'light' || stored === 'dark') {
    return stored;
  }
  return null;
};

/**
 * 로컬 스토리지에 테마 저장
 */
const saveThemeToStorage = (storageKey: string, theme: Theme): void => {
  if (typeof localStorage === 'undefined') return;
  localStorage.setItem(`${storageKey}-theme`, theme);
};

/**
 * 로컬 스토리지에서 언어 로드
 */
const loadLanguageFromStorage = (storageKey: string): Language | null => {
  if (typeof localStorage === 'undefined') return null;
  const stored = localStorage.getItem(`${storageKey}-language`);
  if (stored === 'en' || stored === 'ko') {
    return stored;
  }
  return null;
};

/**
 * 로컬 스토리지에 언어 저장
 */
const saveLanguageToStorage = (
  storageKey: string,
  language: Language,
): void => {
  if (typeof localStorage === 'undefined') return;
  localStorage.setItem(`${storageKey}-language`, language);
};

/**
 * DOM에 테마 클래스 적용
 */
const applyThemeToDOM = (theme: Theme): void => {
  if (typeof document === 'undefined') return;
  const htmlElement = document.documentElement;
  if (theme === 'dark') {
    htmlElement.classList.add('dark');
    htmlElement.classList.remove('light');
  } else {
    htmlElement.classList.add('light');
    htmlElement.classList.remove('dark');
  }
};

/**
 * DOM에 언어 속성 적용
 */
const applyLanguageToDOM = (language: Language): void => {
  if (typeof document === 'undefined') return;
  document.documentElement.setAttribute('lang', language);
};

// ===== Store Implementation =====
export const useSettingStore = create<SettingStore>()(
  subscribeWithSelector(
    immer((set, get) => ({
      // --- 초기 상태 ---
      isInitialized: false,
      status: ApplicationStatus.IDLE,
      error: null,
      lastUpdated: Date.now(),
      theme: DEFAULT_SETTING_STATE.theme,
      language: DEFAULT_SETTING_STATE.language,
      config: DEFAULT_SETTING_CONFIG,
      _isSettingUp: false,
      _isTearingDown: false,

      // --- 액션 구현 ---

      /**
       * createInitializer가 호출할 initialize 액션
       */
      initialize: async () => {
        if (get().isInitialized) {
          console.warn('SettingStore already initialized');
          return;
        }
        set({ isInitialized: true });
      },

      setup: async (config?: Partial<SettingConfig>) => {
        const state = get();

        // 중복 setup 방지
        if (state._isSettingUp || state.status === ApplicationStatus.READY) {
          console.warn('Setting setup already in progress or completed');
          return;
        }

        if (state.status !== ApplicationStatus.IDLE) {
          console.warn(`Cannot setup from status: ${state.status}`);
          return;
        }

        set({
          status: ApplicationStatus.SETTING_UP,
          _isSettingUp: true,
          error: null,
        });

        try {
          // 설정 병합
          const mergedConfig = { ...DEFAULT_SETTING_CONFIG, ...config };

          // 테마 결정 순서: localStorage > 시스템 테마 > 기본값
          let resolvedTheme: Theme = DEFAULT_SETTING_STATE.theme;
          let resolvedLanguage: Language = DEFAULT_SETTING_STATE.language;

          if (mergedConfig.enablePersistence) {
            const storedTheme = loadThemeFromStorage(mergedConfig.storageKey);
            const storedLanguage = loadLanguageFromStorage(
              mergedConfig.storageKey,
            );

            if (storedTheme) {
              resolvedTheme = storedTheme;
            } else if (mergedConfig.autoDetectSystemTheme) {
              resolvedTheme = detectSystemTheme();
            }

            if (storedLanguage) {
              resolvedLanguage = storedLanguage;
            }
          } else if (mergedConfig.autoDetectSystemTheme) {
            resolvedTheme = detectSystemTheme();
          }

          // 상태 설정
          set({
            config: mergedConfig,
            theme: resolvedTheme,
            language: resolvedLanguage,
            status: ApplicationStatus.READY,
            isInitialized: true,
            _isSettingUp: false,
            error: null,
            lastUpdated: Date.now(),
          });

          // DOM에 적용
          applyThemeToDOM(resolvedTheme);
          applyLanguageToDOM(resolvedLanguage);

          console.log('Setting setup completed:', {
            theme: resolvedTheme,
            language: resolvedLanguage,
          });
        } catch (error) {
          console.error('Setting setup failed:', error);
          set({
            status: ApplicationStatus.ERROR,
            error: handleError(error),
            _isSettingUp: false,
          });
          throw error;
        }
      },

      teardown: async () => {
        const state = get();

        if (state._isTearingDown || state.status === ApplicationStatus.IDLE) {
          console.warn('Teardown already in progress or completed');
          return;
        }

        set({ _isTearingDown: true });

        try {
          set({
            status: ApplicationStatus.IDLE,
            _isTearingDown: false,
            lastUpdated: Date.now(),
          });

          console.log('Setting teardown completed');
        } catch (error) {
          console.error('Teardown error:', error);
          set({
            error: handleError(error),
            _isTearingDown: false,
          });
        }
      },

      destroy: () => {
        set({
          isInitialized: false,
          status: ApplicationStatus.IDLE,
          theme: DEFAULT_SETTING_STATE.theme,
          language: DEFAULT_SETTING_STATE.language,
          config: DEFAULT_SETTING_CONFIG,
          error: null,
          _isSettingUp: false,
          _isTearingDown: false,
          lastUpdated: Date.now(),
        });
        console.log('SettingStore destroyed');
      },

      setTheme: (theme: Theme) => {
        const { config } = get();

        set((state) => {
          state.theme = theme;
          state.lastUpdated = Date.now();
        });

        // DOM에 적용
        applyThemeToDOM(theme);

        // 로컬 스토리지에 저장
        if (config.enablePersistence) {
          saveThemeToStorage(config.storageKey, theme);
        }

        console.log('Theme changed to:', theme);
      },

      toggleTheme: () => {
        const { theme, config } = get();
        const newTheme: Theme = theme === 'dark' ? 'light' : 'dark';

        set((state) => {
          state.theme = newTheme;
          state.lastUpdated = Date.now();
        });

        // DOM에 적용
        applyThemeToDOM(newTheme);

        // 로컬 스토리지에 저장
        if (config.enablePersistence) {
          saveThemeToStorage(config.storageKey, newTheme);
        }

        console.log('Theme toggled to:', newTheme);
      },

      setLanguage: (language: Language) => {
        const { config } = get();

        set((state) => {
          state.language = language;
          state.lastUpdated = Date.now();
        });

        // DOM에 적용
        applyLanguageToDOM(language);

        // 로컬 스토리지에 저장
        if (config.enablePersistence) {
          saveLanguageToStorage(config.storageKey, language);
        }

        console.log('Language changed to:', language);
      },

      resetToDefaults: () => {
        const { config } = get();

        set((state) => {
          state.theme = DEFAULT_SETTING_STATE.theme;
          state.language = DEFAULT_SETTING_STATE.language;
          state.lastUpdated = Date.now();
        });

        // DOM에 적용
        applyThemeToDOM(DEFAULT_SETTING_STATE.theme);
        applyLanguageToDOM(DEFAULT_SETTING_STATE.language);

        // 로컬 스토리지 정리
        if (config.enablePersistence && typeof localStorage !== 'undefined') {
          localStorage.removeItem(`${config.storageKey}-theme`);
          localStorage.removeItem(`${config.storageKey}-language`);
        }

        console.log('Settings reset to defaults');
      },
    })),
  ),
);

// Store 초기화 헬퍼
export const initializeSettingStore = createInitializer(
  useSettingStore,
  'SettingStore',
);
