import { ReactNode, createContext, useEffect, useState } from 'react';
import { useContext } from 'react';
import { router, useSegments } from 'expo-router';
import * as SecureStore from 'expo-secure-store';

import axios from 'axios';
import { EXPO_PUBLIC_API_URL } from '@env';
import { User } from '../types/user';

import {  authenticationService } from '../service/authService';

type AuthProvider = {
    user: User | null;
    login: (username: string, password: string) => Promise<boolean>;
    logout: () => void;
    setUser: React.Dispatch<React.SetStateAction<User | null>>;
};

function useProtectedRoute(user: User | null) {
    const segments = useSegments();

    useEffect(() => {
        const inAuthGroup = segments[0] === '(auth)';
        if (!user && inAuthGroup) {
            router.replace('/login');
        } else if (user && !inAuthGroup) {
            router.replace('/(auth)/(tabs)/(home)/mainPage');
        }
    }, [user, segments]);
}

export const AuthContext = createContext<AuthProvider>({
    user: null,
    login: async () => false,
    logout: () => {},
    setUser: () => {}
});

export function useAuth() {
    const context = useContext(AuthContext);
    if (!context) {
        throw new Error('useAuth must be used within a <AuthProvider />');
    }
    return context;
}

export default function AuthProvider({ children }: { children: ReactNode }) {
    const [user, setUser] = useState<User | null>(null);

    const login = async (username: string, password: string) => {
        try {
            const loggedInUser = await authenticationService.login(
                username,
                password
            );
            if (loggedInUser) {
                const userInfo = await getUserFromAccessToken();
                if (userInfo) {
                    setUser((prevUser) => ({
                        ...prevUser,
                        address: userInfo.address,
                        birthday: userInfo.birthday,
                        email: userInfo.email,
                        gender: userInfo.gender,
                        nickname: userInfo.nickname,
                        phone: userInfo.phone
                    }));
                }
                return true;
            } else {
                return false;
            }
        } catch (error) {
            console.error('Login error:', error);
            return false;
        }
    };

    const getUserFromAccessToken = async () => {
        const token = await SecureStore.getItemAsync('accessToken');
        try {
            const res = await axios.get(
                `${EXPO_PUBLIC_API_URL}/clients/customer`,
                {
                    headers: {
                        Authorization: `Bearer ${token}`
                    }
                }
            );
            const items = {
                address: res.data.address,
                birthday: res.data.birthday,
                gender: res.data.gender,
                email: res.data.email,
                nickname: res.data.nickname,
                phone: res.data.phone
            };
            return items;
        } catch (error) {
            console.error('GetUser Error:', error);
        }
    };

    const logout = async () => {
        try {
            await authenticationService.logout();
            setUser(null);
            router.replace('/login');
        } catch (error) {
            console.log('error during logout', error);
        }
    };

    useProtectedRoute(user);

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