import axios from "axios";
import DeviceInfo from "react-native-device-info";
import config from "../../config/config";
import { setAuthentication } from "../../utils/authentication";
import { axiosErrorMessage, getErrorMessage } from "../../utils/helper";
import {
  AUTHENTICATION_FAILED,
  AUTHENTICATION_REQUEST,
  AUTHENTICATION_SUCCESS,
  HISTORY_REMOVE_ALL,
  REMOVE_ALL_FAILED_JOB,
} from "./types";

// Offline constants (no declaration file needed)
const OFFLINE_STATUS_CHANGED = "OFFLINE_STATUS_CHANGED" as const;
const RESET_STATE = "RESET_STATE" as const;

// Modern Base64
const encodeBase64 = (str: string) => Buffer.from(str, "utf-8").toString("base64");

interface AuthResponse {
  access_token: string;
  token_type?: string;
  expires_in?: number;
  refresh_token?: string;
}

interface UserCredentials {
  username: string;
  password: string;
}

interface RootState {
  userInfo: {
    userInfo: {
      access_token: string;
    };
  };
}

// ------------------------
// Offline / Redux Actions
// ------------------------

export const triggerStatusChange = () => (dispatch: any) => {
  dispatch({ type: OFFLINE_STATUS_CHANGED, payload: { online: true } });
};

export const clearQueue = () => (dispatch: any) => {
  dispatch({ type: RESET_STATE, payload: {} });
};

export const partialLogout = () => (dispatch: any) => {
  console.log("inside partialLogout");
  return dispatch({ type: AUTHENTICATION_SUCCESS, payload: {} });
};

// ------------------------
// Logout with async/await
// ------------------------

export const logout = () => {
  return async (dispatch: any, getState: () => RootState) => {
    const { userInfo } = getState();

    // 1. Get the token directly. No need for Promise.resolve and await here.
    const token = userInfo.userInfo.access_token;

    // 2. Await the promise from getUniqueId to get the actual string value.
    const deviceId = await DeviceInfo.getUniqueId();

    // Prepare FormData
    const formData = new FormData();
    formData.append("token", token);
    formData.append("device", deviceId); // Now you are passing a string

    // Clear all redux states
    dispatch({ type: AUTHENTICATION_SUCCESS, payload: {} });
    dispatch({ type: "INIT_DATA_FETCH_TIME", payload: "" });
    dispatch({ type: "PERMISSION_SUCCESS", payload: {} });
    dispatch({ type: HISTORY_REMOVE_ALL, payload: {} });
    dispatch({ type: RESET_STATE, payload: {} });
    dispatch({ type: REMOVE_ALL_FAILED_JOB, payload: {} });

    try {
      const res = await axios.post(
        `${config.apiserver}/api/v1/notifications/remove-device-token`,
        formData,
        { headers: { "Content-Type": "multipart/form-data" } }
      );
      return res;
    } catch (error) {
      console.log("remove device token error", error);
      return error;
    }
  };
};



// ------------------------
// Authenticate with async/await
// ------------------------

export const authenticate = (formData: FormData, navigation: any) => {
  return async (dispatch: any): Promise<string | undefined> => {
    dispatch({ type: AUTHENTICATION_REQUEST, payload: {} });

    try {
      const res = await axios.post<AuthResponse>(
        `${config.apiserver}/oauth/token?_format=json`,
        formData
      );

      if (res?.data?.access_token) {
        dispatch({ type: AUTHENTICATION_SUCCESS, payload: res.data });
        setAuthentication(res.data.access_token);
        return res.data.access_token;
      } else {
        dispatch({
          type: AUTHENTICATION_FAILED,
          payload: "Something went wrong while authenticating",
        });
        return undefined;
      }
    } catch (error) {
      dispatch({ type: AUTHENTICATION_FAILED, payload: getErrorMessage(error) });
      return undefined;
    }
  };
};

// ------------------------
// Offline / redux-offline action
// ------------------------

export const authenticateOffline = (userCredentials: UserCredentials) => ({
  type: AUTHENTICATION_REQUEST,
  payload: { userCredentials },
  meta: {
    offline: {
      effect: {
        url: "http://192.168.1.137/users",
        method: "GET",
        auth: {
          username: "admin",
          password: "admin",
        },
      },
      commit: { type: AUTHENTICATION_SUCCESS, meta: { userCredentials } },
      rollback: { type: AUTHENTICATION_FAILED, meta: { userCredentials } },
    },
  },
});

// ------------------------
// Reset Password
// ------------------------

export const resetPassword = (password: string) => {
  return async (dispatch: any) => {
    const formData = new FormData();
    formData.append("password", password);

    try {
      const res = await axios.post(
        `${config.apiserver}/api/v1/user/change-password`,
        formData
      );
      return res;
    } catch (error) {
      console.log("change password error", getErrorMessage(error));
      axiosErrorMessage("Error in password reset", error);
      return error;
    }
  };
};
