import React, { createContext, useReducer, useEffect } from 'react';

import { isTokenValid, getAccessTokenFromCookie, getUserFromToken } from 'src/axios/authService';

// 사용자 타입 정의
export interface Member {
    memberId: string;
    memberName: string;
}

// 인증 상태 타입 정의
interface AuthState {
    isAuthenticated: boolean;
    member: Member | null;
    loading: boolean;
    error: string | null;
}

// 액션 타입 정의
type AuthAction =
    | { type: 'LOGIN_SUCCESS'; payload: { member: Member; token: string } }
    | { type: 'LOGOUT' }
    | { type: 'AUTH_ERROR'; payload: string }
    | { type: 'CLEAR_ERROR' }
    | { type: 'SET_LOADING' }
    | { type: 'MEMBER_LOADED'; payload: Member };

// 초기 상태
const initialState: AuthState = {
    isAuthenticated: false,
    member: null,
    loading: true,
    error: null
};

// Context 타입 정의
export interface AuthContextType {
    state: AuthState;
    dispatch: React.Dispatch<AuthAction>;
    login: (token: string, member: Member) => void;
    logout: () => void;
}

// Context 생성
export const AuthContext = createContext<AuthContextType>({
    state: initialState,
    dispatch: () => null,
    login: () => null,
    logout: () => null
});

// 리듀서 함수
const authReducer = (state: AuthState, action: AuthAction): AuthState => {
    switch (action.type) {
        case 'LOGIN_SUCCESS':
            localStorage.setItem('accessToken', action.payload.token);
            return {
                ...state,
                isAuthenticated: true,
                member: action.payload.member,
                loading: false,
                error: null
            };
        case 'LOGOUT':
            localStorage.removeItem('accessToken');
            return {
                ...state,
                isAuthenticated: false,
                member: null,
                loading: false,
                error: null
            };
        case 'AUTH_ERROR':
            localStorage.removeItem('accessToken');
            return {
                ...state,
                isAuthenticated: false,
                member: null,
                loading: false,
                error: action.payload
            };
        case 'CLEAR_ERROR':
            return {
                ...state,
                error: null
            };
        case 'SET_LOADING':
            return {
                ...state,
                loading: true
            };
        case 'MEMBER_LOADED':
            return {
                ...state,
                isAuthenticated: true,
                member: action.payload,
                loading: false
            };
        default:
            return state;
    }
};

// Provider 컴포넌트
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    const [state, dispatch] = useReducer(authReducer, initialState);

    // 로그인 함수
    const login = (token: string, member: Member) => {
        dispatch({
            type: 'LOGIN_SUCCESS',
            payload: { token, member }
        });
    };

    // 로그아웃 함수
    const logout = () => {
        dispatch({ type: 'LOGOUT' });
    };

    // 초기 인증 상태 확인
    useEffect(() => {
        const loadUser = async () => {
            // localStorage 또는 Cookie에서 토큰 확인
            let token = localStorage.getItem('accessToken') || getAccessTokenFromCookie();

            if (!token || !isTokenValid(token)) {
                dispatch({ type: 'LOGOUT' });
                return;
            }

            try {
                // 토큰이 쿠키에만 있고 localStorage에 없으면 저장해줌 (일관성 유지)
                if (!localStorage.getItem('accessToken')) {
                    localStorage.setItem('accessToken', token);
                }

                const decodedToken = getUserFromToken(token);
                if (decodedToken) {
                    const member: Member = {
                        memberId: decodedToken.memberId,
                        memberName: decodedToken.memberName
                    };
                    dispatch({ type: 'MEMBER_LOADED', payload: member });
                } else {
                    dispatch({ type: 'AUTH_ERROR', payload: 'Invalid token' });
                }
            } catch (error) {
                dispatch({ type: 'AUTH_ERROR', payload: 'Authentication failed' });
            }
        };

        loadUser();
    }, []);

    return (
        <AuthContext.Provider value={{ state, dispatch, login, logout }}>
            {children}
        </AuthContext.Provider>
    );
};