/**
 * 품목기준관리 Zustand Store
 *
 * 하이브리드 로딩 전략:
 * 1단계: Zustand (메모리 캐시)
 * 2단계: sessionStorage (브라우저 세션)
 * 3단계: API/Redis (백엔드 캐시, 10분 TTL)
 * 4단계: Database (영구 저장소)
 */

import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import { useShallow } from 'zustand/react/shallow';
import type { PageConfig, PageType, DynamicFormData } from '@/types/master-data';
import { fetchPageConfigByType, invalidatePageConfigCache } from '@/lib/api/master-data';

// ===== Store 타입 정의 =====

interface MasterDataStore {
  // === State ===

  // 현재 테넌트 ID (캐시 격리용)
  currentTenantId: number | null;

  // 페이지 구성 캐시 (페이지 타입별)
  pageConfigs: Record<PageType, PageConfig | null>;

  // 로딩 상태
  loading: Record<PageType, boolean>;

  // 에러 상태
  errors: Record<PageType, string | null>;

  // 선택된 페이지 타입
  selectedPageType: PageType | null;

  // 폼 데이터 (임시 저장)
  formData: Record<string, DynamicFormData>;

  // === Actions ===

  // 테넌트 ID 설정 (로그인 시 호출)
  setCurrentTenantId: (tenantId: number | null) => void;

  // 페이지 구성 가져오기 (하이브리드 로딩)
  // tenantId 파라미터는 선택적 (없으면 currentTenantId 사용)
  fetchPageConfig: (pageType: PageType, tenantId?: number) => Promise<PageConfig | null>;

  // 페이지 구성 캐시 무효화
  invalidateConfig: (pageType: PageType) => void;

  // 모든 캐시 무효화
  invalidateAllConfigs: () => void;

  // 선택된 페이지 타입 설정
  setSelectedPageType: (pageType: PageType | null) => void;

  // 폼 데이터 관리
  setFormData: (id: string, data: DynamicFormData) => void;
  getFormData: (id: string) => DynamicFormData | undefined;
  clearFormData: (id: string) => void;

  // 로딩/에러 상태
  setLoading: (pageType: PageType, loading: boolean) => void;
  setError: (pageType: PageType, error: string | null) => void;

  // 초기화
  reset: () => void;
}

// ===== 초기 상태 =====

const createEmptyPageConfigs = (): Record<PageType, PageConfig | null> => ({
  'item-master': null,
  'quotation': null,
  'sales-order': null,
  'formula': null,
  'pricing': null,
});

const initialState = {
  currentTenantId: null as number | null,
  pageConfigs: createEmptyPageConfigs(),
  loading: {} as Record<PageType, boolean>,
  errors: {} as Record<PageType, string | null>,
  selectedPageType: null as PageType | null,
  formData: {} as Record<string, DynamicFormData>,
};

// ===== sessionStorage 유틸리티 =====

const STORAGE_PREFIX = 'page_config_';
const STORAGE_TIMESTAMP_SUFFIX = '_timestamp';
const CACHE_TTL = 10 * 60 * 1000; // 10분

/**
 * 테넌트별 캐시 키 생성
 * tenantId가 있으면: page_config_{tenantId}_{pageType}
 * tenantId가 없으면: page_config_{pageType} (하위 호환)
 */
function getStorageKey(tenantId: number | null, pageType: PageType): string {
  return tenantId != null
    ? `${STORAGE_PREFIX}${tenantId}_${pageType}`
    : `${STORAGE_PREFIX}${pageType}`;
}

/**
 * sessionStorage에서 페이지 구성 가져오기
 */
function getConfigFromSessionStorage(tenantId: number | null, pageType: PageType): PageConfig | null {
  if (typeof window === 'undefined') return null;

  try {
    const key = getStorageKey(tenantId, pageType);
    const cachedData = window.sessionStorage.getItem(key);
    const timestamp = window.sessionStorage.getItem(`${key}${STORAGE_TIMESTAMP_SUFFIX}`);

    if (!cachedData || !timestamp) return null;

    // TTL 확인
    const cacheAge = Date.now() - parseInt(timestamp, 10);
    if (cacheAge > CACHE_TTL) {
      // 만료된 캐시 삭제
      window.sessionStorage.removeItem(key);
      window.sessionStorage.removeItem(`${key}${STORAGE_TIMESTAMP_SUFFIX}`);
      return null;
    }

    return JSON.parse(cachedData);
  } catch (error) {
    console.error(`[sessionStorage] Failed to get config for ${pageType}:`, error);
    return null;
  }
}

/**
 * sessionStorage에 페이지 구성 저장
 */
function setConfigToSessionStorage(tenantId: number | null, pageType: PageType, config: PageConfig): void {
  if (typeof window === 'undefined') return;

  try {
    const key = getStorageKey(tenantId, pageType);
    window.sessionStorage.setItem(key, JSON.stringify(config));
    window.sessionStorage.setItem(`${key}${STORAGE_TIMESTAMP_SUFFIX}`, Date.now().toString());
  } catch (error) {
    console.error(`[sessionStorage] Failed to set config for ${pageType}:`, error);
  }
}

/**
 * sessionStorage에서 페이지 구성 삭제
 */
function removeConfigFromSessionStorage(tenantId: number | null, pageType: PageType): void {
  if (typeof window === 'undefined') return;

  try {
    const key = getStorageKey(tenantId, pageType);
    window.sessionStorage.removeItem(key);
    window.sessionStorage.removeItem(`${key}${STORAGE_TIMESTAMP_SUFFIX}`);
  } catch (error) {
    console.error(`[sessionStorage] Failed to remove config for ${pageType}:`, error);
  }
}

// ===== Store 생성 =====

export const useMasterDataStore = create<MasterDataStore>()(
  devtools(
    (set, get) => ({
      // Initial state
      ...initialState,

      // ===== 테넌트 관리 =====

      setCurrentTenantId: (tenantId: number | null) =>
        set({ currentTenantId: tenantId }, false, 'setCurrentTenantId'),

      // ===== 하이브리드 로딩 전략 =====

      fetchPageConfig: async (pageType: PageType) => {
        const { pageConfigs, loading, errors, currentTenantId } = get();

        // 🔒 이미 로딩 중이면 중복 요청 방지
        if (loading[pageType]) {
          return pageConfigs[pageType] || null;
        }

        // 🔒 최근에 에러가 발생했으면 재시도 방지 (캐시 무효화 전까지)
        if (errors[pageType] && pageConfigs[pageType] === null) {
          return null;
        }

        // 1️⃣ 메모리 캐시 확인 (Zustand)
        if (pageConfigs[pageType]) {
          return pageConfigs[pageType];
        }

        // 2️⃣ sessionStorage 확인
        const cachedConfig = getConfigFromSessionStorage(currentTenantId, pageType);
        if (cachedConfig) {

          // 메모리에 저장
          set(
            (state) => ({
              pageConfigs: {
                ...state.pageConfigs,
                [pageType]: cachedConfig,
              },
            }),
            false,
            'fetchPageConfig/cacheHit'
          );

          return cachedConfig;
        }

        // 3️⃣ API 요청 (Redis/Database)

        try {
          get().setLoading(pageType, true);
          get().setError(pageType, null);

          const config = await fetchPageConfigByType(pageType);

          if (!config) {
            console.warn(`⚠️ [Config Not Found] ${pageType}`);
            get().setError(pageType, '페이지 구성을 찾을 수 없습니다.');

            // 에러 상태지만 null을 캐시에 저장하여 재시도 방지
            set(
              (state) => ({
                pageConfigs: {
                  ...state.pageConfigs,
                  [pageType]: null,
                },
              }),
              false,
              'fetchPageConfig/notFound'
            );

            return null;
          }

          // 캐시 저장 (메모리 + sessionStorage)
          set(
            (state) => ({
              pageConfigs: {
                ...state.pageConfigs,
                [pageType]: config,
              },
            }),
            false,
            'fetchPageConfig/success'
          );

          setConfigToSessionStorage(currentTenantId, pageType, config);

          return config;
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : '페이지 구성 조회 실패';
          console.error(`❌ [API Error] ${pageType}:`, error);

          get().setError(pageType, errorMessage);

          // 에러 상태를 캐시에 저장하여 재시도 방지
          set(
            (state) => ({
              pageConfigs: {
                ...state.pageConfigs,
                [pageType]: null,
              },
            }),
            false,
            'fetchPageConfig/error'
          );

          return null;
        } finally {
          get().setLoading(pageType, false);
        }
      },

      // ===== 캐시 무효화 =====

      invalidateConfig: (pageType: PageType) => {
        const { pageConfigs, currentTenantId } = get();
        const newConfigs = { ...pageConfigs };
        delete newConfigs[pageType];

        set(
          { pageConfigs: newConfigs },
          false,
          'invalidateConfig'
        );

        removeConfigFromSessionStorage(currentTenantId, pageType);

      },

      invalidateAllConfigs: () => {
        const { currentTenantId } = get();
        const pageTypes: PageType[] = ['item-master', 'quotation', 'sales-order', 'formula', 'pricing'];

        pageTypes.forEach((pageType) => {
          removeConfigFromSessionStorage(currentTenantId, pageType);
        });

        set(
          { pageConfigs: createEmptyPageConfigs() },
          false,
          'invalidateAllConfigs'
        );

        // 서버 캐시도 무효화
        invalidatePageConfigCache().catch((error) => {
          console.error('[Cache Invalidation Error]:', error);
        });

      },

      // ===== 페이지 타입 선택 =====

      setSelectedPageType: (pageType) =>
        set(
          { selectedPageType: pageType },
          false,
          'setSelectedPageType'
        ),

      // ===== 폼 데이터 관리 =====

      setFormData: (id, data) =>
        set(
          (state) => ({
            formData: {
              ...state.formData,
              [id]: data,
            },
          }),
          false,
          'setFormData'
        ),

      getFormData: (id) => {
        return get().formData[id];
      },

      clearFormData: (id) =>
        set(
          (state) => {
            const newFormData = { ...state.formData };
            delete newFormData[id];
            return { formData: newFormData };
          },
          false,
          'clearFormData'
        ),

      // ===== 로딩/에러 상태 =====

      setLoading: (pageType, loading) =>
        set(
          (state) => ({
            loading: {
              ...state.loading,
              [pageType]: loading,
            },
          }),
          false,
          'setLoading'
        ),

      setError: (pageType, error) =>
        set(
          (state) => ({
            errors: {
              ...state.errors,
              [pageType]: error,
            },
          }),
          false,
          'setError'
        ),

      // ===== 초기화 =====

      reset: () => {
        // 1. 메모리 캐시 초기화
        set(initialState, false, 'reset');

        // 2. sessionStorage 캐시도 정리 (프리픽스 기반으로 모든 테넌트 캐시 제거)
        if (typeof window !== 'undefined') {
          Object.keys(window.sessionStorage).forEach(key => {
            if (key.startsWith(STORAGE_PREFIX)) {
              window.sessionStorage.removeItem(key);
            }
          });
        }
      },
    }),
    {
      name: 'MasterDataStore',
    }
  )
);

// ===== Selector Hooks (성능 최적화) =====

/**
 * 특정 페이지 타입의 구성만 구독
 */
export const usePageConfig = (pageType: PageType) =>
  useMasterDataStore((state) => state.pageConfigs[pageType]);

/**
 * 로딩 상태만 구독
 */
export const usePageConfigLoading = (pageType: PageType) =>
  useMasterDataStore((state) => state.loading[pageType]);

/**
 * 에러 상태만 구독
 */
export const usePageConfigError = (pageType: PageType) =>
  useMasterDataStore((state) => state.errors[pageType]);

/**
 * 선택된 페이지 타입만 구독
 */
export const useSelectedPageType = () =>
  useMasterDataStore((state) => state.selectedPageType);

/**
 * 액션만 가져오기 (리렌더링 방지)
 */
export const useMasterDataActions = () =>
  useMasterDataStore(
    useShallow((state) => ({
      fetchPageConfig: state.fetchPageConfig,
      invalidateConfig: state.invalidateConfig,
      invalidateAllConfigs: state.invalidateAllConfigs,
      setSelectedPageType: state.setSelectedPageType,
      setFormData: state.setFormData,
      getFormData: state.getFormData,
      clearFormData: state.clearFormData,
      reset: state.reset,
    }))
  );

// ===== 타입 추출 =====

export type { MasterDataStore };