/* eslint-disable no-unused-vars */
import axios, { AxiosResponse } from 'axios';
import {
  createContext,
  type Dispatch,
  type PropsWithChildren,
  type SetStateAction,
  useEffect,
  useState
} from 'react';

import * as authHelper from '../_helpers';
import { type AuthModel, type UserModel } from '@/auth';
import { apiConfig } from '@/config/api.config';
import { doSaveLogActivity } from '@/actions/GlobalActions';

const API_URL = apiConfig.service_dashboard;

export const LOGIN_URL = `${API_URL}/login`;
export const FORGOT_PASSWORD_URL = `${API_URL}/reset_password`;
export const RESET_PASSWORD_URL = `${API_URL}/update_password`;
export const GET_USER_URL = `${API_URL}/user/detail`;

interface AuthContextProps {
  loading: boolean;
  setLoading: Dispatch<SetStateAction<boolean>>;
  auth: AuthModel | undefined;
  saveAuth: (auth: AuthModel | undefined) => void;
  currentUser: UserModel | undefined;
  setCurrentUser: Dispatch<SetStateAction<UserModel | undefined>>;
  login: (email: string, password: string) => Promise<void>;
  requestPasswordResetLink: (email: string) => Promise<void>;
  changePassword: (token: string, password: string, password_confirmation: string) => Promise<void>;
  getUser: () => Promise<AxiosResponse<any> | {}>;
  logout: () => void;
  verify: () => Promise<void>;
}

const AuthContext = createContext<AuthContextProps | null>(null);

const AuthProvider = ({ children }: PropsWithChildren) => {
  const [loading, setLoading] = useState(true);
  const [auth, setAuth] = useState<AuthModel | undefined>(authHelper.getAuth());
  const [currentUser, setCurrentUser] = useState<UserModel | undefined>();

  const verify = async () => {
    if (auth) {
      try {
        const { data: user } = await getUser();
        const createCacheUser = {
          name: user.name,
          email: user.email,
          username: user.username,
          role_name: auth.role_name,
          statusbalance: user.role.status_balance,
        };
        localStorage.setItem('user', JSON.stringify(createCacheUser));
      } catch {
        saveAuth(undefined);
        setCurrentUser(undefined);
      }
    }
  };

  const saveAuth = (auth: AuthModel | undefined) => {
    setAuth(auth);
    if (auth) {
      authHelper.setAuth(auth);
    } else {
      authHelper.removeAuth();
    }
  };

  const login = async (username: string, password: string) => {
    try {
      const { data: auth } = await axios
        .post(LOGIN_URL, { username, password }) // , { headers: { 'Access-Control-Allow-Origin': "*" }}
        .then((response) => response.data);

      saveAuth({ ...auth.token, id: auth.user.id, role_name: auth.role_name, user: auth.user });
      setCurrentUser(auth.user);
      const createActivity = {
        module: 'Login',
        description: `Login`,
        action: 'l'
      };
      doSaveLogActivity(createActivity);
    } catch (error: any) {
      throw error;
    }
  };

  const requestPasswordResetLink = async (email: string) => {
    await axios.put(FORGOT_PASSWORD_URL + '/' + email);
  };

  const changePassword = async (token: string, password: string, retype_password: string) => {
    await axios.put(`${RESET_PASSWORD_URL}/${token}`, {
      password,
      retype_password
    });
  };

  const getUser = async () => {
    let _axios = await axios
      .get(`${GET_USER_URL}/${authHelper.getAuth()?.id}`)
      .then((response) => response.data.data);

    return { data: _axios };
  };

  const logout = async () => {
    const createActivity = {
      module: 'Logout',
      description: `Logout`,
      action: 'O'
    };
    await doSaveLogActivity(createActivity);

    saveAuth(undefined);
    setCurrentUser(undefined);
  };

  return (
    <AuthContext.Provider
      value={{
        loading,
        setLoading,
        auth,
        saveAuth,
        currentUser,
        setCurrentUser,
        login,
        // register,
        requestPasswordResetLink,
        changePassword,
        getUser,
        logout,
        verify
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

export { AuthContext, AuthProvider };
