import React, { useReducer } from "react";
import { getSiteImagesAPI } from "./services/settingService";
import MkdSDK from "./utils/MkdSDK";
import { tokenExpireError } from "./authContext";

// Add constants
export const REQUEST_LOADING = "REQUEST_LOADING";
export const REQUEST_SUCCESS = "REQUEST_SUCCESS";
export const REQUEST_FAILED = "REQUEST_FAILED";
export const SET_GLOBAL_PROPERTY = "SET_GLOBAL_PROPERTY";

export const RequestItems = {
  deleteModel: "deleteModel",
  customRequest: "customRequest",
  // Add any other request items you need
};

export const GlobalContext = React.createContext();

const initialState = {
  globalMessage: "",
  toastStatus: "success",
  isOpen: true,
  path: "",
  projectRow: null,
  showProfile: false,
  siteLogo: "",
  landingImage: "",
  assignedIdeas: [],
  masterProjects: [],
  subProjectLyrics: [],
  songSubProjects: [],
  subProjectLyricsEditWorkOrder: [],
  songSubProjectsEditWorkOrder: [],
  projectIdeas: [],
  eightcount_id: null,
  subproject_update: false,
  loading: false,
  success: false,
  error: false,
  data: [],
};

const reducer = (state, action) => {
  switch (action.type) {
    case "SNACKBAR":
      return {
        ...state,
        globalMessage: action.payload.message,
        toastStatus: action.payload.toastStatus,
      };
    case "SETPATH":
      return {
        ...state,
        path: action.payload.path,
      };
    case "OPEN_SIDEBAR":
      return {
        ...state,
        isOpen: action.payload.isOpen,
      };
    case "SET_PROJECT_ROW":
      return {
        ...state,
        projectRow: action.payload,
      };
    case "TOGGLE_PROFILE":
      return {
        ...state,
        showProfile: action.payload.showProfile,
      };
    case "SITE_IMAGES":
      return {
        ...state,
        siteLogo: action.payload.siteLogo,
        landingImage: action.payload.landingImage,
      };
    case "SET_ASSIGNED_IDEAS":
      return {
        ...state,
        assignedIdeas: action.payload,
      };
    case "SET_SUB_PROJECT_LYRICS":
      return {
        ...state,
        subProjectLyrics: action.payload,
      };
    case "SET_SONG_SUB_PROJECTS":
      return {
        ...state,
        songSubProjects: action.payload,
      };
    case "SET_SUB_PROJECT_LYRICS_EDIT_WORK_ORDER":
      return {
        ...state,
        subProjectLyricsEditWorkOrder: action.payload,
      };
    case "SET_SONG_SUB_PROJECTS_EDIT_WORK_ORDER":
      return {
        ...state,
        songSubProjectsEditWorkOrder: action.payload,
      };
    case "SET_PROJECT_IDEAS":
      return {
        ...state,
        projectIdeas: action.payload,
      };
    case "SET_SUBPROJECT_UPDATE":
      return {
        ...state,
        subproject_update: action.payload,
      };
    case "SET_CURRENT_EIGHTCOUNT_ID":
      return {
        ...state,
        eightcount_id: action.payload,
      };
    case "SET_CURRENT_PENDING_LENGTH":
      return {
        ...state,
        pendingLength: action.payload,
      };
    case REQUEST_LOADING:
      return {
        ...state,
        [action.item]: {
          ...state[action?.item],
          loading: action?.payload,
        },
      };
    case REQUEST_SUCCESS:
      return {
        ...state,
        [action.item]: {
          ...state[action?.item],
          ...action?.payload,
          data: { ...state[action?.item]?.data, ...action?.payload?.data },
          error: false,
          success: true,
          loading: false,
        },
      };
    case REQUEST_FAILED:
      return {
        ...state,
        [action.item]: {
          ...state[action?.item],
          ...action?.payload,
          error: true,
          success: false,
          loading: false,
        },
      };
    case SET_GLOBAL_PROPERTY:
      if (action.property.includes(".")) {
        const [prop, field] = action.property.split(".");
        return {
          ...state,
          [prop]: { ...state[prop], [field]: action?.payload },
        };
      } else {
        return {
          ...state,
          [action.property]: action?.payload,
        };
      }
    default:
      return state;
  }
};

/**
 * @param {"success"| "error" | "warning"} toastStatus
 * @param {any} dispatch
 * @param {string} message
 * @param {number} timeout
 */

export const showToast = (
  dispatch,
  message,
  timeout = 3000,
  toastStatus = "success"
) => {
  dispatch({
    type: "SNACKBAR",
    payload: {
      message,
      toastStatus,
    },
  });

  setTimeout(() => {
    dispatch({
      type: "SNACKBAR",
      payload: {
        message: "",
      },
    });
  }, timeout);
};

export const setGlobalProjectRow = (dispatch, data) => {
  dispatch({
    type: "SET_PROJECT_ROW",
    payload: data,
  });
};

const GlobalProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const fetchSiteImages = async () => {
    const result = await getSiteImagesAPI();
    if (!result.error) {
      let siteLogo = "";
      let landingImage = "";
      if (result.list.length > 0) {
        console.log(result.list);
        result.list.forEach((row, index) => {
          if (index == 2) {
            siteLogo = `${row.setting_value}`;
          }
          if (row.setting_key === "landing_image") {
            landingImage = `${row.setting_value}`;
          }
        });
      }
      dispatch({
        type: "SITE_IMAGES",
        payload: {
          siteLogo: `https://app.equalityrecords.com/${siteLogo}`,
          landingImage: `https://app.equalityrecords.com/${landingImage}`,
        },
      });
    }
  };

  React.useEffect(() => {
    fetchSiteImages();
  }, []);

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

export default GlobalProvider;

// Add new action creators after the existing ones
export const setGLobalProperty = (dispatch, data, property) => {
  dispatch({
    property,
    type: SET_GLOBAL_PROPERTY,
    payload: data,
  });
};

export const setLoading = (dispatch, data, item) => {
  dispatch({
    item,
    type: REQUEST_LOADING,
    payload: data,
  });
};

export const dataSuccess = (dispatch, data, item) => {
  dispatch({
    item,
    type: REQUEST_SUCCESS,
    payload: data,
  });
};

export const dataFailure = (dispatch, data, item) => {
  dispatch({
    item,
    type: REQUEST_FAILED,
    payload: data,
  });
};

export const getList = async (
  globalDispatch,
  authDispatch,
  table,
  options = {},
  state = null
) => {
  const sdk = new MkdSDK();
  setLoading(globalDispatch, true, state ?? table);
  try {
    const result = await sdk.callRawAPI(
      `/v4/api/records/${table}`,
      "GET",
      options
    );
    if (!result?.error) {
      dataSuccess(
        globalDispatch,
        { message: result?.message, data: result?.list },
        state ?? table
      );
      return { error: false, data: result?.list };
    }
    return result;
  } catch (error) {
    const message = error?.response?.data?.message ?? error?.message;
    dataFailure(globalDispatch, { message }, table);
    tokenExpireError(authDispatch, message);
    return { error: true, message };
  }
};

export const getManyByIds = async (
  globalDispatch,
  authDispatch,
  table,
  ids = [],
  join = [],
  allowToast = true
) => {
  const sdk = new MkdSDK();
  try {
    const result = await sdk.callRawAPI(
      `/v4/api/records/${table}/ids`,
      "POST",
      { ids, join }
    );
    if (!result?.error) {
      return { error: false, data: result?.list };
    }
    return result;
  } catch (error) {
    const message = error?.response?.data?.message ?? error?.message;
    if (allowToast) {
      showToast(globalDispatch, message, 4000, "error");
    }
    tokenExpireError(authDispatch, message);
    return { error: true, message };
  }
};

export const getSingleModel = async (
  globalDispatch,
  authDispatch,
  table,
  id,
  options = {
    isPublic: false,
    method: "GET",
    join: [],
    state: null,
    allowToast: true,
  }
) => {
  const sdk = new MkdSDK();
  setLoading(globalDispatch, true, options?.state ?? table);
  try {
    const result = await sdk.callRawAPI(
      `/v4/api/records/${table}/${id}`,
      options?.method,
      { join: options?.join }
    );
    if (!result?.error) {
      dataSuccess(
        globalDispatch,
        { message: result?.message, data: result?.model },
        options?.state ?? table
      );
      return { error: false, data: result?.model };
    }
    return result;
  } catch (error) {
    const message = error?.response?.data?.message ?? error?.message;
    if (options?.allowToast) {
      showToast(globalDispatch, message, 4000, "error");
    }
    tokenExpireError(authDispatch, message);
    return { error: true, message };
  }
};

export const createRequest = async (
  globalDispatch,
  authDispatch,
  table,
  payload,
  allowToast = true
) => {
  const sdk = new MkdSDK();
  try {
    const result = await sdk.callRawAPI(
      `/v4/api/records/${table}`,
      "POST",
      payload
    );
    if (!result?.error) {
      if (allowToast) {
        showToast(globalDispatch, result?.message, 4000, "success");
      }
      return { error: false, data: result?.model };
    }
    return result;
  } catch (error) {
    const message = error?.response?.data?.message ?? error?.message;
    if (allowToast) {
      showToast(globalDispatch, message, 4000, "error");
    }
    tokenExpireError(authDispatch, message);
    return { error: true, message };
  }
};

export const updateRequest = async (
  globalDispatch,
  authDispatch,
  table,
  id,
  payload,
  allowToast = true
) => {
  const sdk = new MkdSDK();
  try {
    const result = await sdk.callRawAPI(
      `/v4/api/records/${table}/${id}`,
      "PATCH",
      payload
    );
    if (!result?.error) {
      if (allowToast) {
        showToast(globalDispatch, result?.message, 4000, "success");
      }
      return { error: false, data: result?.model };
    }
    return result;
  } catch (error) {
    const message = error?.response?.data?.message ?? error?.message;
    if (allowToast) {
      showToast(globalDispatch, message, 4000, "error");
    }
    tokenExpireError(authDispatch, message);
    return { error: true, message };
  }
};

export const deleteRequest = async (
  globalDispatch,
  authDispatch,
  table,
  id,
  payload,
  allowToast = true
) => {
  const sdk = new MkdSDK();
  try {
    const result = await sdk.callRawAPI(
      `/v4/api/records/${table}/${id}`,
      "DELETE",
      payload
    );
    if (!result?.error) {
      if (allowToast) {
        showToast(globalDispatch, result?.message, 4000, "success");
      }
      return { error: false };
    }
    return result;
  } catch (error) {
    const message = error?.response?.data?.message ?? error?.message;
    if (allowToast) {
      showToast(globalDispatch, message, 4000, "error");
    }
    tokenExpireError(authDispatch, message);
    return { error: true, message };
  }
};

export const customRequest = async (
  globalDispatch,
  authDispatch,
  options = { endpoint: "", payload: null, method: "GET" },
  state = RequestItems.customRequest,
  allowToast = true,
  signal = null
) => {
  if (!options.endpoint) {
    showToast(
      globalDispatch,
      "options.endpoint is a required field",
      4000,
      "error"
    );
    return { error: true };
  }
  const sdk = new MkdSDK();
  setLoading(globalDispatch, true, state);
  try {
    const result = await sdk.customRequest(
      options?.endpoint,
      options?.method,
      options?.payload,
      signal
    );
    if (!result?.error) {
      dataSuccess(
        globalDispatch,
        { message: result?.message, data: result?.data, error: false },
        state
      );
      if (allowToast) {
        showToast(
          globalDispatch,
          result?.message ?? "Success",
          4000,
          "success"
        );
      }
      return {
        ...result,
        error: false,
        data: result?.data || result?.model || result?.list,
        message: result?.message,
      };
    }
    return {
      ...result,
      error: true,
      validation: result?.validation,
      message: result?.message,
    };
  } catch (error) {
    const message = error?.response?.data?.message ?? error?.message;
    dataFailure(globalDispatch, { message, error: true }, state);
    if (allowToast) {
      showToast(globalDispatch, message, 4000, "error");
    }
    tokenExpireError(authDispatch, message);
    return { ...error?.response?.data, error: true, message };
  }
};
