import { create } from 'zustand'; // Zustand 상태 관리 라이브러리
import { persist } from 'zustand/middleware'; // Zustand 상태 영속화 미들웨어
// TypeScript/Node 모듈 규칙 - 폴더를 import 하면 자동으로 그 안의 index 파일을 찾는 규칙
import { authApi } from '@/lib/api'; // tsconfig.json의 paths 규칙에 따라 절대경로 import
import { UserDto, LoginDto, SignupDto } from '@/types/auth.types';

/**
 * 인증 Store 상태 - 인증 관련 값 안올때 확인
 * 상태(State)를 중앙에서 관리하는 저장소
 * login.page 프론트에서 요청을 받으면 백엔드로 요청을 전송하고 받은 데이터를 저장하고 관리
 */
interface AuthState {
  // 상태
  user: UserDto | null; // 현재 로그인한 사용자 정보
  accessToken: string | null; // JWT 액세스 토큰
  refreshToken: string | null; // JWT 리프레시 토큰
  isAuthenticated: boolean; // 로그인 여부


  // 각 페이지의 호출된 함수 실행
  login: (dto: LoginDto) => Promise<void>; // 로그인
  signup: (dto: SignupDto) => Promise<void>; // 회원가입
  logout: () => Promise<void>; // 로그아웃
  refreshAuth: () => Promise<void>; // 토큰 갱신
  loadProfile: () => Promise<void>; // 프로필 불러오기
  clearAuth: () => void; // 인증 정보 초기화 (클라이언트에서)
}

/**
 * 인증 Store
 *
 * @description
 * JWT 토큰 기반 인증 상태 관리
 * - localStorage에 토큰 자동 저장 (persist)
 * - 로그인/로그아웃/회원가입/토큰 갱신 기능
 */

// useAuthStore는 Zustand의 create 함수로 만든 커스텀 스토어 훅
// Zustand import 후 그 반환값을 useAuthStore에 할당
// import { useAuthStore } from "@/store/auth-store"; // 스토어에서 토큰/초기화 사용
export const useAuthStore = create<AuthState>()(  
  persist( // persist 미들웨어로 전체 상태를 자동 저장,복원/ partialize(state)쓰게되면 저장할 필드만 선별하는거라함 
  // persist미들웨어를 붙이면 set으로 상태를 바꿀때 선택된 필드가 자동으로 localStorage에 저장
    (set, get) => ({
      // 초기 상태
      user: null,
      accessToken: null,
      refreshToken: null,
      isAuthenticated: false,

      /**
       * @description 로그인 페이지에서 백엔드 API로 요청 전송 authApi.login(dto)
       * 백엔드에서 토큰을 반환하면 프론트에서 로컬 스토리지에 저장
       */
      login: async (dto: LoginDto) => {
        try {
          const response = await authApi.login(dto); // authApi의 login 함수 호출
          //authApi는 auth.api.ts에 정의되어 있음
          //import { authApi } from '@/lib/api'; 임포트를 @/lib/api 로 했기 때문에
          //자동으로 index.ts를 찾아가서 authApi를 가져옴
          //직접 auth.api.ts를 import 하려면 '@/lib/api/auth.api'로 해야함
          
          // 받아온 결과를 상태에 저장
          // Zustand 상태 업데이트 (persist 미들웨어가 자동으로 localStorage에 저장)
          set({ 
            user: response.user,
            accessToken: response.accessToken,
            refreshToken: response.refreshToken || null,
            isAuthenticated: true,
          });
        } catch (error) {
          console.error('로그인 실패:', error);
          throw error;
        }
      },

      /**
       * 회원가입
       */
      signup: async (dto: SignupDto) => {
        try {
          const response = await authApi.signup(dto);

          // Zustand 상태 업데이트 (persist 미들웨어가 자동으로 localStorage에 저장)
          set({
            user: response.user,
            accessToken: response.accessToken,
            refreshToken: response.refreshToken || null,
            isAuthenticated: true,
          });
        } catch (error) {
          console.error('회원가입 실패:', error);
          throw error;
        }
      },

      /**
       * 로그아웃
       */
      logout: async () => {
        try {
          await authApi.logout();
        } catch (error) {
          console.error('로그아웃 요청 실패:', error);
        } finally {
          // Zustand 상태 초기화 (persist 미들웨어가 자동으로 localStorage에서 삭제)
          set({
            user: null,
            accessToken: null,
            refreshToken: null,
            isAuthenticated: false,
          });
        }
      },

      /**
       * 토큰 갱신
       */
      refreshAuth: async () => {
        try {
          const { refreshToken } = get();

          if (!refreshToken) {
            throw new Error('리프레시 토큰이 없습니다.');
          }

          const response = await authApi.refreshToken(refreshToken);

          // Zustand 상태 업데이트 (persist 미들웨어가 자동으로 localStorage에 저장)
          set({
            user: response.user,
            accessToken: response.accessToken,
            refreshToken: response.refreshToken || refreshToken,
            isAuthenticated: true,
          });
        } catch (error) {
          // 토큰 갱신 실패 시 로그아웃 처리
          get().clearAuth();
          throw error;
        }
      },

      /**
       * 프로필 불러오기
       */
      loadProfile: async () => {
        try {
          const profile = await authApi.getProfile();

          set({
            user: profile,
            isAuthenticated: true,
          });
        } catch (error) {
          console.error('프로필 불러오기 실패:', error);
          throw error;
        }
      },

      /**
       * 인증 정보 초기화 (클라이언트 측)
       */
      clearAuth: () => {
        // Zustand 상태 초기화 (persist 미들웨어가 자동으로 localStorage에서 삭제)
        set({
          user: null,
          accessToken: null,
          refreshToken: null,
          isAuthenticated: false,
        });
      },
    }),
    {
      name: 'auth-storage', // localStorage 키 이름
      partialize: (state) => ({
        // localStorage에 저장할 필드만 선택
        user: state.user,
        accessToken: state.accessToken,
        refreshToken: state.refreshToken,
        isAuthenticated: state.isAuthenticated,
      }),
    }
  )
);
