// See the Electron documentation for details on how to use preload scripts:
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
import { contextBridge, ipcRenderer } from 'electron';
import { EVENT_NAMES } from './constants/define';
import { useState } from 'react';
// import { safeInvoke } from './utilities/grpcHelper';

contextBridge.exposeInMainWorld('common', {
  [EVENT_NAMES.COMMON.REMOVE_EVENT_LISTENER]: (eventName, callback) => {
    ipcRenderer.removeListener(eventName, callback);
  },
  [EVENT_NAMES.COMMON.CLOSE_WINDOW]: () => ipcRenderer.send(EVENT_NAMES.COMMON.CLOSE_WINDOW),
  [EVENT_NAMES.COMMON.NAVIGATE_CHANGE_PASSWORD_PAGE]: (callback) =>
    ipcRenderer.on(EVENT_NAMES.COMMON.NAVIGATE_CHANGE_PASSWORD_PAGE, callback),
  [EVENT_NAMES.COMMON.SAVE_CSV_FILE]: (data) => ipcRenderer.send(EVENT_NAMES.COMMON.SAVE_CSV_FILE, data),
});

contextBridge.exposeInMainWorld('recorder', {
  [EVENT_NAMES.CLIENT_RECORDER.RECORD]: (url) => ipcRenderer.send(EVENT_NAMES.CLIENT_RECORDER.RECORD, url),
  [EVENT_NAMES.CLIENT_RECORDER.PAUSE]: () => ipcRenderer.send(EVENT_NAMES.CLIENT_RECORDER.PAUSE),
  [EVENT_NAMES.CLIENT_RECORDER.RESUME]: () => ipcRenderer.send(EVENT_NAMES.CLIENT_RECORDER.RESUME),
  [EVENT_NAMES.CLIENT_RECORDER.STOP]: () => ipcRenderer.send(EVENT_NAMES.CLIENT_RECORDER.STOP),
  [EVENT_NAMES.CLIENT_RECORDER.REPLAY]: (eventLogs) => ipcRenderer.send(EVENT_NAMES.CLIENT_RECORDER.REPLAY, eventLogs),
  [EVENT_NAMES.CLIENT_RECORDER.INDICATE_SELECTOR]: (eventLogs, stepId, reSelectType) =>
    ipcRenderer.send(EVENT_NAMES.CLIENT_RECORDER.INDICATE_SELECTOR, eventLogs, stepId, reSelectType),
  [EVENT_NAMES.CLIENT_RECORDER.DETAIL_COLUMN_TABLE_RECORD]: (eventLogs, stepId, linkColumnPosition) =>
    ipcRenderer.send(EVENT_NAMES.CLIENT_RECORDER.DETAIL_COLUMN_TABLE_RECORD, {
      eventLogs,
      stepId,
      linkColumnPosition,
    }),
  [EVENT_NAMES.CLIENT_RECORDER.ON_UPDATE_EVENT_LOG]: (callback) => {
    ipcRenderer.on(EVENT_NAMES.CLIENT_RECORDER.ON_UPDATE_EVENT_LOG, callback);
  },
  [EVENT_NAMES.CLIENT_RECORDER.ON_UPDATE_SELECTOR]: (callback) => {
    ipcRenderer.on(EVENT_NAMES.CLIENT_RECORDER.ON_UPDATE_SELECTOR, callback);
  },
  [EVENT_NAMES.CLIENT_RECORDER.ON_UPDATE_DETAIL_SCRAPE_COLUMN]: (callback) => {
    ipcRenderer.on(EVENT_NAMES.CLIENT_RECORDER.ON_UPDATE_DETAIL_SCRAPE_COLUMN, callback);
  },
  [EVENT_NAMES.CLIENT_RECORDER.ON_CLOSE_RECORDER]: (callback) => {
    ipcRenderer.on(EVENT_NAMES.CLIENT_RECORDER.ON_CLOSE_RECORDER, callback);
  },

});


contextBridge.exposeInMainWorld('token', {
  getToken: () => localStorage.getItem('token'),

  [EVENT_NAMES.ELECTRONSTORE.USER_DATA]: (callback) => {
    ipcRenderer.on('user-data', (event, data) => {
        console.log('Received user data in renderer process:', data);
        callback(event, data);
    });
},

});


contextBridge.exposeInMainWorld('requestrememberuser', {
  requestUserData: () => ipcRenderer.send('request-user-data'),
});


contextBridge.exposeInMainWorld('grpcAPIs', {
  [EVENT_NAMES.AUTHENTICATION.LOGIN]: (email, password) =>
    safeInvoke(EVENT_NAMES.AUTHENTICATION.LOGIN, email, password),
  
  [EVENT_NAMES.AUTHENTICATION.LOGOUT]: () =>
    safeInvoke(EVENT_NAMES.AUTHENTICATION.LOGOUT),
  [EVENT_NAMES.AUTHENTICATION.REGISTER]: (email, password) =>
    safeInvoke(EVENT_NAMES.AUTHENTICATION.REGISTER, email, password),

  [EVENT_NAMES.AUTHENTICATION.INITIATE_RESET_PASSWORD]: (attributes) => {
    safeInvoke(EVENT_NAMES.AUTHENTICATION.INITIATE_RESET_PASSWORD, attributes);
  },
  [EVENT_NAMES.AUTHENTICATION.CHANGE_PASSWORD]: (attributes) =>
    safeInvoke(EVENT_NAMES.AUTHENTICATION.CHANGE_PASSWORD, attributes),

  [EVENT_NAMES.ESSENTIAL.RETRIEVE]: () => safeInvoke(EVENT_NAMES.ESSENTIAL.RETRIEVE),

  [EVENT_NAMES.JOBS.LIST]: (attributes) => safeInvoke(EVENT_NAMES.JOBS.LIST, attributes),
  [EVENT_NAMES.JOBS.VIEW]: (id) => safeInvoke(EVENT_NAMES.JOBS.VIEW, id),
  [EVENT_NAMES.JOBS.CREATE]: (attributes) => safeInvoke(EVENT_NAMES.JOBS.CREATE, attributes),
  [EVENT_NAMES.JOBS.UPDATE]: (attributes) => safeInvoke(EVENT_NAMES.JOBS.UPDATE, attributes),
  [EVENT_NAMES.JOBS.DELETE]: (jobId) => safeInvoke(EVENT_NAMES.JOBS.DELETE, jobId),
  [EVENT_NAMES.JOBS.RUN_JOB]: (jobId) => safeInvoke(EVENT_NAMES.JOBS.RUN_JOB, jobId),

  [EVENT_NAMES.USERS.LIST]: (attributes) => safeInvoke(EVENT_NAMES.USERS.LIST, attributes),
  [EVENT_NAMES.USERS.VIEW]: (id) => safeInvoke(EVENT_NAMES.USERS.VIEW, id),
  [EVENT_NAMES.USERS.CREATE]: (attributes) => safeInvoke(EVENT_NAMES.USERS.CREATE, attributes),
  [EVENT_NAMES.USERS.UPDATE]: (attributes) => safeInvoke(EVENT_NAMES.USERS.UPDATE, attributes),

  [EVENT_NAMES.COUNTIES.LIST]: (attributes) => safeInvoke(EVENT_NAMES.COUNTIES.LIST, attributes),
  [EVENT_NAMES.COUNTIES.DELETE]: (id) => safeInvoke(EVENT_NAMES.COUNTIES.DELETE, id),
  [EVENT_NAMES.COUNTIES.CREATE]: (attributes) => safeInvoke(EVENT_NAMES.COUNTIES.CREATE, attributes),
  [EVENT_NAMES.COUNTIES.UPDATE]: (attributes) => safeInvoke(EVENT_NAMES.COUNTIES.UPDATE, attributes),

  [EVENT_NAMES.RECORDS.LIST]: (attributes) => safeInvoke(EVENT_NAMES.RECORDS.LIST, attributes),
  [EVENT_NAMES.SCRAPING_DATA.VIEW]: (attributes) => safeInvoke(EVENT_NAMES.SCRAPING_DATA.VIEW, attributes),
  [EVENT_NAMES.SCRAPING_DATA.UPDATE]: (attributes) => safeInvoke(EVENT_NAMES.SCRAPING_DATA.UPDATE, attributes),
});

/**
 * Invokes a gRPC method and returns a promise that resolves with the response.
 * If the gRPC method returns an error, the promise will reject with the error message.
 * @param {string} event - The name of the gRPC method to invoke.
 * @param  {...any} args - The arguments to pass to the gRPC method.
 * @return {Promise} A promise that resolves with the response or rejects with the error message.
 */
export const safeInvoke = (event, ...args) => {
  return ipcRenderer
    .invoke(event, ...args)
    .then((response) => response)
    .catch((error) => {
      throw new Error(getGrpcErrorMessage(error));
    });
};

/**
 * Extracts and returns the custom message from a gRPC error.
 *
 * gRPC automatically prefixes error messages with a standard string (e.g., "Error invoking remote method 'login': ").
 * This function removes the standard prefix and returns only the custom message (e.g., "Email or password is incorrect").
 *
 * @param {Error} error - The gRPC error object.
 * @return {string} The custom error message.
 */
export const getGrpcErrorMessage = (error) => {
  const message = error.message || '';
  const customMessageStart = message.indexOf(':') + 1; // Find the second colon
  const customMessage = message.slice(customMessageStart).trim();
  return customMessage;
};
