'use client';

import { useMemo, useEffect, useReducer, useCallback, useState } from 'react';

import axios, {  axiosInstance3, endpoints } from '@/utils/axios';

import { AuthContext } from './auth-context';
import { setSession, isValidToken } from './utils';
import { AuthUserType, ActionMapType, AuthStateType } from '../types';
import { jwtDecode, JwtPayload } from 'jwt-decode';
import { getTokenInfo } from '@/utils/token';
import { IUser, RequestLoginActivity } from '@/shared/types/user';
import { useRouter } from 'next/navigation';
import { GATEWAY, USER_API } from '@/config-global';


// ----------------------------------------------------------------------
/**
 * NOTE:
 * We only build demo at basic level.
 * Customer will need to do some extra handling yourself if you want to extend the logic and other features...
 */
// ----------------------------------------------------------------------
interface CustomJwtPayload extends JwtPayload {
  realm_access?: {
    roles: string[];
  };
}
enum Types {
  INITIAL = 'INITIAL',
  LOGIN = 'LOGIN',
  REGISTER = 'REGISTER',
  LOGOUT = 'LOGOUT',
}

type Payload = {
  [Types.INITIAL]: {
    user: AuthUserType;
  };
  [Types.LOGIN]: {
    user: AuthUserType;
  };
  [Types.REGISTER]: {
    user: AuthUserType;
  };
  [Types.LOGOUT]: undefined;
};

type ActionsType = ActionMapType<Payload>[keyof ActionMapType<Payload>];
//-------- User statique 

export const users = [
  {
    id: '8864c717-587d-472a-929a-8e5f298024da-1',
    displayName: 'Jaydon Frankie',
    email: 'manageragency@stunar.com',
    password: 'manageragency1234',
    photoURL: `assets/images/avatars/avatar_default.jpg`,
    phoneNumber: '+40 777666555',
    country: 'United States',
    address: '90210 Broadway Blvd',
    state: 'California',
    city: 'San Francisco',
    zipCode: '94116',
    about: 'Praesent turpis. Phasellus viverra nulla ut metus varius laoreet. Phasellus tempus.',
    role: 'manageragency',
    isPublic: true,
  },
  {
    id: '8864c717-587d-472a-929a-8e5f298024da-2',
    displayName: 'agent',
    email: 'client@stunar.com',
    password: 'client1234',
    photoURL: 'chemin/vers/photo.jpg',
    phoneNumber: 'numéro de téléphone',
    ountry: 'United States',
    address: '90210 Broadway Blvd',
    state: 'California',
    city: 'San Francisco',
    zipCode: '94116',
    about: 'Praesent turpis. Phasellus viverra nulla ut metus varius laoreet. Phasellus tempus.',
    role: 'client',
    isPublic: true,
  },
  {
    id: '8864c717-587d-472a-929a-8e5f298024da-2',
    displayName: 'agent',
    email: 'admin@stunar.com',
    password: 'admin1234',
    photoURL: 'chemin/vers/photo.jpg',
    phoneNumber: 'numéro de téléphone',
    ountry: 'United States',
    address: '90210 Broadway Blvd',
    state: 'California',
    city: 'San Francisco',
    zipCode: '94116',
    about: 'Praesent turpis. Phasellus viverra nulla ut metus varius laoreet. Phasellus tempus.',
    role: 'admin',
    isPublic: true,
  },
  {
    id: '8864c717-587d-472a-929a-8e5f298024da-2',
    displayName: 'agent',
    email: 'employee@stunar.com',
    password: 'employee1234',
    photoURL: 'chemin/vers/photo.jpg',
    phoneNumber: 'numéro de téléphone',
    ountry: 'United States',
    address: '90210 Broadway Blvd',
    state: 'California',
    city: 'San Francisco',
    zipCode: '94116',
    about: 'Praesent turpis. Phasellus viverra nulla ut metus varius laoreet. Phasellus tempus.',
    role: 'employee',
    isPublic: true,
  },
  {
    id: '8864c717-587d-472a-929a-8e5f298024da-2',
    displayName: 'agent',
    email: 'user@stunar.com',
    password: 'user1234',
    photoURL: 'chemin/vers/photo.jpg',
    phoneNumber: 'numéro de téléphone',
    ountry: 'United States',
    address: '90210 Broadway Blvd',
    state: 'California',
    city: 'San Francisco',
    zipCode: '94116',
    about: 'Praesent turpis. Phasellus viverra nulla ut metus varius laoreet. Phasellus tempus.',
    role: 'user',
    isPublic: true,
  },
  
];

  

// ----------------------------------------------------------------------

const initialState: AuthStateType = {
  user: null,
  loading: true,
};

const reducer = (state: AuthStateType, action: ActionsType) => {
  if (action.type === Types.INITIAL) {
    return {
      loading: false,
      user: action.payload.user,
    };
  }
  if (action.type === Types.LOGIN) {
    return {
      ...state,
      user: action.payload.user,
    };
  }
  if (action.type === Types.REGISTER) {
    return {
      ...state,
      user: action.payload.user,
    };
  }
  if (action.type === Types.LOGOUT) {
    return {
      ...state,
      user: null,
    };
  }
  return state;
};

// ----------------------------------------------------------------------

export const JWT_SECRET = 'minimal-secret-key';

export const JWT_EXPIRES_IN = '3 days';

type Props = {
  children: React.ReactNode;
};

export function AuthProvider({ children }: Props) {
  const [state, dispatch] = useReducer(reducer, initialState);
  const [userState, setUserState] = useState<IUser | null>(null);
  const router = useRouter();
  const accessToken = typeof window !== 'undefined' ? localStorage.getItem("token") : null;
  const storedUserInfo = accessToken ? getTokenInfo(accessToken) : null;
  const STORAGE_KEY = 'accessToken';

  const initialize = useCallback(async () => {
    try {
      const accessToken = sessionStorage.getItem(STORAGE_KEY);

      if (accessToken && isValidToken(accessToken)) {
        setSession(accessToken);

        const res = await axios.get(endpoints.auth.me);

        const { user } = res.data;

        dispatch({
          type: Types.INITIAL,
          payload: {
            user: {
              ...user,
              accessToken,
            },
          },
        });
      } else {
        dispatch({
          type: Types.INITIAL,
          payload: {
            user: null,
          },
        });
      }
    } catch (error) {
      console.error(error);
      dispatch({
        type: Types.INITIAL,
        payload: {
          user: null,
        },
      });
    }
  }, []);

  useEffect(() => {
    initialize();
  }, [initialize]);

  

  useEffect(() => {
    const initialize = async () => {
      // Get current path
      const currentPath = window.location.pathname;
      
      // Skip auth check for verification page
      if (currentPath.includes('/auth/verify-email')) {
        return;
      }

      if (accessToken && storedUserInfo) {
        if (!storedUserInfo.isValid) {
          try {
            localStorage.removeItem("token");
            localStorage.removeItem("refreshToken");
            localStorage.removeItem("expirationDurationInSec");
            router.push('/auth/jwt/login');
          } catch (error) {
            console.error("Error during logout process:", error);
          }
        }
      } else {
        // Only redirect to login for protected routes
        const isPublicRoute = [
          '/auth/jwt/login',
          '/auth/jwt/register',
          '/auth/verify-email',
          '/auth/forgot-password',
        ].some(route => currentPath.startsWith(route));

        if (!isPublicRoute) {
          router.push('/auth/jwt/login');
        }
      }
    };
  
    initialize();
  }, [accessToken, storedUserInfo, userState?.activityLog]);
  // LOGIN
  
  const login = useCallback(async (email: string, password: string): Promise<void> => {
    try {
      const response = await axiosInstance3.post('/auth/signin', {
        username: email,
        password: password,
      });
      const result = await response.data;
      const decodedToken = jwtDecode<CustomJwtPayload>(result.token);
      const accessToken = result.token;
      const roles = decodedToken.realm_access?.roles || [];
    
      const role = roles.includes('USER') ? 'user' : roles.includes('ADMIN') ? 'admin' : 'employee';
    
      localStorage.setItem('role', role);
      const response_user = await axiosInstance3.get('/user', {
        params: {
          email: email,
        },
      });
    const user = await response_user.data;
      
      sessionStorage.setItem(STORAGE_KEY, accessToken);
  
      setSession(accessToken);
  
      dispatch({
        type: Types.LOGIN,
        payload: {
          user: {
            ...user,
            accessToken,
          },
        },
      });
  
    } catch (error) {
      throw new Error("Invalid email or password");
    }
  }, []);
  

  // REGISTER
  const register = useCallback(
    async (email: string, password: string, firstName: string, lastName: string) => {
      const data = {
        email,
        password,
        firstName,
        lastName,
      };

      const res = await axios.post(`${GATEWAY}/auth/signup`, data);

      const { accessToken, user } = res.data;

      sessionStorage.setItem(STORAGE_KEY, accessToken);

      dispatch({
        type: Types.REGISTER,
        payload: {
          user: {
            ...user,
            accessToken,
          },
        },
      });
    },
    []
  );

  // LOGOUT
  const logout = useCallback(async () => {
    setSession(null);
    dispatch({
      type: Types.LOGOUT,
    });
  }, []);

  // ----------------------------------------------------------------------

  const checkAuthenticated = state.user ? 'authenticated' : 'unauthenticated';

  const status = state.loading ? 'loading' : checkAuthenticated;

  const memoizedValue = useMemo(
    () => ({
      user: state.user,
      method: 'jwt',
      loading: status === 'loading',
      authenticated: status === 'authenticated',
      unauthenticated: status === 'unauthenticated',
      //
      login,
      register,
      logout,
    }),
    [login, logout, register, state.user, status]
  );

  return <AuthContext.Provider value={memoizedValue}>{children}</AuthContext.Provider>;
}

