/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable react/jsx-key */
/* eslint-disable consistent-return */
/* eslint-disable radix */
/* eslint-disable promise/no-nesting */
/* eslint-disable compat/compat */
/* eslint-disable react/button-has-type */
import { observer } from 'mobx-react';
import { ReactNode, useEffect, useState } from 'react';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import Grid from '@mui/material/Grid';
import enLocale from 'date-fns/locale/en-GB';
import { makeStyles } from '@mui/styles';
import { useNavigate, useLocation } from 'react-router-dom';
import { ipcRenderer } from 'electron';
import { applySnapshot, getSnapshot } from 'mobx-keystone';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { LocalizationProvider } from '@mui/x-date-pickers';
import Footer from './components/partials/Footer';
import Header from './components/partials/Header';
import { getRootStore, RootStore } from './models/root-store';
import Ticket from './models/Application/Ticket';
import PrintEngine from './components/elements/print/PrintEngine';
import Log from './models/Logs/Log';
import Report from './models/Reports/Report';

type Props = {
  children: ReactNode;
};

// 3rd level, after Routes.tsx
function App(props: Props) {
  const [rootStore] = useState(() => getRootStore());
  const { children } = props;
  const history = useNavigate();
  const [showPrintUI, setShowPrintUI] = useState(false);
  const [basket, setBasket] = useState<Ticket[]>();
  const location = useLocation();

  const getTheTheme = () => {
    const blackTheme = {
      palette: {
        mode: 'dark',
        primary: {
          main: rootStore.layout.primaryColor,
          contrastText: '#fff',
        },
        secondary: {
          main: rootStore.layout.secondaryColor,
        },
        background: {
          default: rootStore.layout.componentBackgroundColor,
          paper: rootStore.layout.paperBackgroundColor,
        },
      },
      typography: {
        h3: {
          fontSize: '3.2rem',
        },
        h4: {
          color: 'white',
        },
      },
    };

    const whiteTheme = {
      palette: {
        primary: {
          main: rootStore.layout.primaryColor,
          contrastText: '#fff',
        },
        secondary: {
          main: rootStore.layout.secondaryColor,
        },
        background: {
          default: rootStore.layout.componentBackgroundColor,
          paper: rootStore.layout.paperBackgroundColor,
        },
      },

      typography: {
        h3: {
          fontSize: '3.2rem',
        },
        h4: {
          color: 'white',
        },
      },
    };
    if (rootStore.settings.darkMode) {
      return blackTheme;
    }
    return whiteTheme;
  };
  const [themeUsed, setThemeUsed] = useState(createTheme(getTheTheme()));

  useEffect(() => {
    if (rootStore.settings.emvDatacap) {
      console.log('now running', rootStore.settings.emvDatacap);
      // We reset the EMV once at startup, this also ensures we do the reset once a day
      (async () => {
        const fetchPostAmount = await ipcRenderer.invoke('datacap-resetEmv', {
          merchantId: rootStore.settings.merchantId,
          operatorId: rootStore.settings.operatorId,
          tranDeviceId: rootStore.settings.tranDeviceId,
          ipEmv: rootStore.settings.ipEMV,
        });
      })();
    }


    ipcRenderer.on('newAutoDiscoverEntry', (event, args) => {
      if (!args) return;
      rootStore.acs01List.addAcs01List(args);
    });
    ipcRenderer.on('newAutoDiscoverApp', (event, args) => {
      if (!args) return;
      rootStore.acs01List.addAppList(args);
    });
    return () => {
      ipcRenderer.removeAllListeners('newAutoDiscoverEntry');
      ipcRenderer.removeAllListeners('newAutoDiscoverApp');
    };
  }, []);

  useEffect(() => {
    const handler = async () => {
      try {
        console.log('[AUTO Batchclose and  summary] signal received in renderer');
        if (!rootStore.settings.emvDatacap) return;
    
        const resp = await ipcRenderer.invoke('datacap-batchSummaryAndClose', {
          merchantId:   rootStore.settings.merchantId,
          operatorId:   rootStore.settings.operatorId,
          tranDeviceId: rootStore.settings.tranDeviceId,
          ipEmv:        rootStore.settings.ipEMV,
          terminalId:   rootStore.settings.terminalId,
        });
    
        // ---- 1) Log the Batch Summary snapshot
        const sum = resp?.summary ?? {};
        const sumR = resp?.summaryResp?.RStream ?? {};
        rootStore.logs.addLog(new Log({
          type: 'BatchSummary',
          subType: 'cron',
          name: 'Batch summary fetched',
          reason: [
            `TerminalID: ${sum.TerminalID ?? sumR.TerminalID ?? ''}`,
            `BatchNo: ${sum.BatchNo ?? sumR.BatchNo ?? ''}`,
            `BatchItemCount: ${sum.BatchItemCount ?? sumR.BatchItemCount ?? ''}`,
            `NetBatchTotal: ${sum.NetBatchTotal ?? sumR.NetBatchTotal ?? ''}`,
          ].join(' | '),
          user: 'System',
        }));
    
        // ---- 2) Log the Batch Close result
        const closeR = resp?.closeResp?.RStream ?? {};
        rootStore.logs.addLog(new Log({
          type: 'BatchClose',
          subType: 'Cron',
          name: resp?.ok ? 'Batch closed successfully' : 'Batch close failed',
          reason: [
            `BatchNo: ${resp?.BatchNo ?? sum.BatchNo ?? closeR.BatchNo ?? ''}`,
            `NetBatchTotal: ${sum.NetBatchTotal ?? closeR.NetBatchTotal ?? ''}`,
            `BatchItemCount: ${sum.BatchItemCount ?? closeR.BatchItemCount ?? ''}`,
            `CmdStatus: ${closeR.CmdStatus ?? ''}`,
            `Code: ${resp?.DSIXReturnCode ?? closeR.DSIXReturnCode ?? ''}`,
            `Msg: ${resp?.TextResponse ?? closeR.TextResponse ?? ''}`,
          ].join(' | '),
          user: 'System',
        }));
    
        console.log('[AUTO CLOSE] result:', resp);
      } catch (e) {
        console.error('[AUTO CLOSE] error:', e);
        rootStore.logs.addLog(new Log({
          type: 'Batch',
          subType: 'Auto-Close',
          name: 'Batch close error',
          reason: String(e),
          user: 'System',
        }));
      }
    };
  
    ipcRenderer.on('auto-batchClose', handler);
    return () => ipcRenderer.removeListener('auto-batchClose', handler);
  }, []);

  // Regular expression to check if string is a valid UUID
  const regexExp =
    /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/gi;

  useEffect(() => {
    ipcRenderer.on('main->mainWindow-serialMessage', (event, args) => {
      // Check if we have simple tickets enabled
      if (rootStore.scannedTicketList.useSimpleTicket) {
        // Look for online code
        if (regexExp.test(args.slice(-36)) === true) {
          return rootStore.settings.setSerialMessage(args.slice(-36));
        }
        // Look for offline code
        const checkForCameCode: number = args.indexOf('[');
        // Offline code not found, so we return the whole message (wich should be the simple message)
        if (checkForCameCode === -1) {
          return rootStore.settings.setSerialMessage(args);
        }
        if (checkForCameCode !== -1) {
          // Offline code found, so we cut it out from the buffer
          const cameCodeData: string = args.slice(checkForCameCode);
          return rootStore.settings.setSerialMessage(cameCodeData);
        }
      }
      // simple tickets are not selected
      // Check if it is a online barcode, for this we cut the last 36 digits from the buffer in order to be sure we don't have thing left in the buffer
      // We would receive something like: "Nc¹&_Nc¹&_AA972062-3595-43FD-8594-2B04BC86F9CC"
      // After .slice(-36) we have: "AA972062-3595-43FD-8594-2B04BC86F9CC"
      if (regexExp.test(args.slice(-36)) === true) {
        return rootStore.settings.setSerialMessage(args.slice(-36));
      }
      // Check for offline barcode
      const checkForCameCode: number = args.indexOf('[');
      if (checkForCameCode !== -1) {
        const cameCodeData: string = args.slice(checkForCameCode);
        return rootStore.settings.setSerialMessage(cameCodeData);
      }
    });

    return () => {
      ipcRenderer.removeAllListeners('main->mainWindow-serialMessage');
    };
  }, [rootStore.settings.serialMessage]);

  useEffect(() => {
    rootStore?.logs.addLog(
      new Log({
        type: 'Application',
        subType: 'Startup',
        name: 'Application started',
        reason: `Application launched successfully`,
        user: 'System',
      })
    );
    ipcRenderer.on('thePath', (event, result) => {
      rootStore.layout.setPathLogo(result);
      rootStore.layout.setCustomLogo(true);
    });
    ipcRenderer.on('workerNetworkId', (event, result) => {
      if (typeof result === 'number') {
        rootStore.settings.setWorkerWindowId(result);
      }
    });
    return () => {
      ipcRenderer.removeAllListeners('workerNetworkId');
      ipcRenderer.removeAllListeners('thePath');
    };
  }, []);

  // Listen to fetch results from workerWindow
  useEffect(() => {
    ipcRenderer.on(
      'workerWindowNetwork->mainWindow-discovery',
      (event, discoveryObject) => {
        rootStore.acs01List.addAcs01List(discoveryObject);
      }
    );
    ipcRenderer.on(
      'workerWindowNetwork->mainWindow-result-newBadgeCode',
      (event, sendCode) => {
        rootStore.settings.setKioskMode(false);
        setTimeout(() => {
          rootStore.settings.setKioskMode(true);
        }, 10000);
      }
    );
    ipcRenderer.on(
      'workerWindowNetwork->mainWindow-result-runFetchRunScenario',
      (event, checkScenario) => {
        if (checkScenario?.result === true) {
          rootStore.scenarioList.setState(true);
        } else {
          rootStore.scenarioList.setState(false);
        }
      }
    );
    ipcRenderer.on(
      'workerWindowNetwork->mainWindow-result-wsPingPong',
      (event, wsOnline) => {
        if (wsOnline) {
          rootStore.acs01List.setLocalStatus(1);
        } else {
          rootStore.acs01List.setLocalStatus(0);
        }
      }
    );
    ipcRenderer.on(
      'workerWindowNetwork->mainWindow-result-wsPingPongFails',
      (event, wsFails) => {
        // By incrementing the ws fails, we redo the useEffect so we can detect a new IP if there is any
        rootStore.acs01List.setWebsocketFails();
      }
    );
    ipcRenderer.on(
      'mainWindow->workerWindowNetwork-result-runFetchLoginLocal',
      (event, loginResult) => {
        if (loginResult?.role === 100) {
          rootStore.acs01List.setLocalStatus(1);
        } else {
          rootStore.acs01List.setLocalStatus(0);
        }
      }
    );
    ipcRenderer.on(
      'mainWindow->workerWindowNetwork-result-runFetchLoginRemote',
      (event, loginRemoteResult) => {
        if (loginRemoteResult?.token) {
          rootStore.acs01List.setRemoteStatus(1);
        } else {
          rootStore.acs01List.setRemoteStatus(0);
        }
      }
    );
    
    ipcRenderer.on(
      'workerWindowNetwork->mainWindow-ws-ticketScanned',
      (_event: any, e: any) => {
        if (e?.ticket) rootStore.settings.setSerialMessage(e.ticket);
      }
    );
    ipcRenderer.on('API-setBackup', (event, args) => {
      if (!args) return;
      const tempRootstore: RootStore = args;
      tempRootstore.acs01List.defaultApp = rootStore.acs01List.defaultApp;
      applySnapshot(getRootStore(), tempRootstore);
    });
    ipcRenderer.on('getBackup', (event, args) => {
      event.sender.send(
        'getBackup-response',
        JSON.stringify(getSnapshot(rootStore))
      );
      // rootStore.acs01List.addAcs01List(args);
    });
    return () => {
      ipcRenderer.removeAllListeners('getBackup');
      ipcRenderer.removeAllListeners('API-setBackup');
      ipcRenderer.removeAllListeners(
        'workerWindowNetwork->mainWindow-ws-ticketScanned'
      );
      ipcRenderer.removeAllListeners(
        'workerWindowNetwork->mainWindow-result-newBadgeCode'
      );
      ipcRenderer.removeAllListeners(
        'workerWindowNetwork->mainWindow-result-runFetchRunScenario'
      );
      ipcRenderer.removeAllListeners(
        'workerWindowNetwork->mainWindow-result-wsPingPong'
      );
      ipcRenderer.removeAllListeners(
        'workerWindowNetwork->mainWindow-result-wsPingPongFails'
      );
      ipcRenderer.removeAllListeners(
        'mainWindow->workerWindowNetwork-result-runFetchLoginLocal'
      );
      ipcRenderer.removeAllListeners(
        'mainWindow->workerWindowNetwork-result-runFetchLoginRemote'
      );
    };
  }, []);

  useEffect(() => {
    ipcRenderer.send('fullScreen', rootStore.settings.fullscreen);
    ipcRenderer.send('autoUpdate', rootStore.settings.autoUpdate);
    ipcRenderer.send('autoStart', rootStore.settings.autoStart);
    ipcRenderer
      .invoke('serialList', '')
      .then((result) => {
        return rootStore.settings.setSerialPortList(result);
      })
      .catch((errors) => {
        return console.log('errors', errors);
      });
    return () => {
      ipcRenderer.removeAllListeners('fullScreen');
      ipcRenderer.removeAllListeners('autoUpdate');
      ipcRenderer.removeAllListeners('autoStart');
    };
  }, [
    rootStore.settings.autoStart,
    rootStore.settings.autoUpdate,
    rootStore.settings.fullscreen,
  ]);

  useEffect(() => {
    const prevValue = -1;
    // Below is to send to ledpanels if they are connected
    async function sendToLedPanelIndirect(counters: any, wsMessage: any) {
      console.log('counters', counters);
      const obj = JSON.parse(JSON.stringify(counters));
      console.log('obj', obj);
      const resultSendToPanel = await ipcRenderer.invoke(
        'mainWindow->main-sendCounterDataForPanel',
        obj,
        wsMessage
      );
    }

    ipcRenderer.on(
      'workerWindowNetwork->mainWindow-ws-counterChanged',
      (event, args) => {
        for (let z = 0; z < rootStore.counterList.counters.length; z += 1) {
          if (args.id === rootStore.counterList.counters[z].id) {
            rootStore.counterList.counters[z].setValue(args.value);
            rootStore.reportsList.addReport(
              new Report({
                type: 'Counter set',
                subType: 'WS-set',
                name: `Counter set to ${args.value}`,
                site: 'Local',
                account: 'NA',
                counterName: args.name,
                counterValue: args.value,
              })
            );
            // Run trough countersGroups
            for (
              let x = 0;
              x < rootStore.counterList.counterGroups.length;
              x += 1
            ) {
              // Run trough countersGroups, counters to set their value
              for (
                let y = 0;
                y < rootStore.counterList.counterGroups[x].counters.length;
                y += 1
              ) {
                if (
                  rootStore.counterList.counterGroups[x].counters[y]
                    .counterId === args.id
                ) {
                  rootStore.counterList.setValue(x, y, args.value);
                  console.log(
                    `1. Match for GROUP ${rootStore.counterList.counterGroups[x].name}: name: ${args.name}, value: ${args.value}`
                  );
                }
              }
            }
            rootStore.reportsList.addReport(
              new Report({
                type: 'Send to LED-panel',
                subType: 'LED-Panel-set',
                name: `Counter set to ${args.value}`,
                site: 'Local',
                account: 'NA',
                counterName: args.name,
                counterValue: args.value,
              })
            );
            sendToLedPanelIndirect(rootStore.counterList.counterGroups, args);
          }
        }
      }
    );

    return () => {
      ipcRenderer.removeAllListeners(
        'workerWindowNetwork->mainWindow-ws-counterChanged'
      );
    };
  }, [rootStore.counterList.counters]);

  useEffect(() => {
    if (showPrintUI !== true) {
      // history.push('/');
      history('/');
    }
  }, []);

  useEffect(() => {
    ipcRenderer.on('setToPrintUI', (event, result) => {
      if (result === true) {
        setShowPrintUI(true);
      } else {
        setShowPrintUI(false);
      }
    });
    return () => {
      ipcRenderer.removeAllListeners('setToPrintUI');
    };
  }, [showPrintUI]);

  useEffect(() => {
    if (showPrintUI === true) {
      if (basket !== rootStore.basket.all) {
        setBasket(rootStore.basket.all);
      }
    }
    return () => {};
  }, [rootStore.basket.all]);

  useEffect(() => {
    if (typeof rootStore.acs01List.defaultAcs01 === 'undefined') return;
    if (
      rootStore.settings.applicationMode === 1 ||
      rootStore.settings.applicationMode === 2 ||
      rootStore.settings.applicationMode === 5 ||
      rootStore.settings.applicationMode === 7
    ) {
      ipcRenderer.postMessage(
        'mainWindow->main-keystoneSync',
        [
          {
            key: 'applicationMode',
            value: rootStore.settings.applicationMode,
          },
          {
            key: 'username',
            value: rootStore.acs01List?.defaultAcs01.username,
          },
          {
            key: 'password',
            value: rootStore.acs01List?.defaultAcs01.password,
          },
          {
            key: 'localUrl',
            value: rootStore.acs01List?.defaultAcs01.localUrl,
          },
          {
            key: 'defaultReaderId',
            value: rootStore.readerList.defaultReaderId,
          },
          {
            key: 'defaultPrinterId',
            value: rootStore.printerList.defaultPrinterId,
          },
          {
            key: 'defaultScenarioConfigured',
            value: rootStore.scenarioList.defaultScenarioConfigured,
          },
          {
            key: 'defaultScenarioId',
            value: rootStore.scenarioList.defaultScenarioId,
          },
          {
            key: 'defaultPrinterBackupId',
            value: rootStore.printerList.defaultPrinterBackupId,
          },
          {
            key: 'defaultPrinterButtonId',
            value: rootStore.printerList.defaultPrinterButtonId,
          },
        ],
        []
      );
    }

    return () => {};
  }, [
    rootStore.settings.applicationMode,
    rootStore.acs01List.discoverStatus,
    rootStore.acs01List.defaultAcs01,
    rootStore.acs01List.defaultAcs01?.localUrl,
    rootStore.acs01List.defaultAcs01?.username,
    rootStore.acs01List.defaultAcs01?.password,
    rootStore.readerList.defaultReaderId,
    rootStore.printerList.defaultPrinterId,
    rootStore.scenarioList.defaultScenarioConfigured,
    rootStore.scenarioList.defaultScenarioId,
    rootStore.printerList.defaultPrinterBackupId,
    rootStore.printerList.defaultPrinterButtonId,
  ]);

  // Set background to primary color when the screensaver is on
  const getBackground = () => {
    if (
      rootStore.settings.screenSaverEnabled &&
      !rootStore.settings.screenSaverState &&
      location.pathname === '/'
    ) {
      return rootStore.layout.primaryColor;
    }
    return rootStore.settings.backgroundColor;
  };

  // Set position to fixed when the screensaver is on
  const getPosition = () => {
    if (
      rootStore.settings.screenSaverEnabled &&
      !rootStore.settings.screenSaverState &&
      location.pathname === '/'
    ) {
      return 'fixed';
    }
    return 'static';
  };

  // const theme = createTheme(getTheTheme());

  useEffect(() => {
    setThemeUsed(createTheme(getTheTheme()));
    return () => {};
  }, [
    rootStore.settings.darkMode,
    rootStore.layout.primaryColor,
    rootStore.layout.secondaryColor,
    rootStore.settings.backgroundColor,
    rootStore.layout.componentBackgroundColor,
    rootStore.layout.paperBackgroundColor,
  ]);
  /*
  const theme = createTheme({
    palette: {
      primary: {
        light: "#757ce8",
        main: rootStore.layout.primaryColor,
        dark: "#002884",
        contrastText: "#fff",
      },
      secondary: {
        main: rootStore.layout.secondaryColor,
      },
    },
    typography: {
      h3: {
        fontSize: "3.2rem",
      },
      h4: {
        color: "white",
      },
    },
  });
*/

  const useStyles = makeStyles({
    container: {
      backgroundColor: getBackground(),
      position: getPosition(),
    },
    mainfooter: {
      backgroundColor: rootStore.layout.footerColor,
      width: '100%',
      height: rootStore.layout.footerHeight,
      bottom: '0',
      position: 'fixed',
      color: 'white',
    },
  });

  const classes = useStyles();
  return (
    <ThemeProvider theme={themeUsed}>
      <LocalizationProvider
        dateAdapter={AdapterDateFns}
        adapterLocale={enLocale}
      >
        {showPrintUI ? (
          <PrintEngine />
        ) : (
          <Grid
            container
            direction="column"
            style={{ minHeight: '100vh' }}
            className={classes.container}
          >
            {rootStore.userList.loggedInUser || rootStore.layout.showHeader ? (
              <Header />
            ) : null}
            <Grid
              container
              spacing={0}
              direction="column"
              alignItems="center"
              justifyContent="center"
              style={{ minHeight: '100%' }}
            >
              {children}
            </Grid>
            {rootStore.layout.showFooter ? (
              <Grid item className={classes.mainfooter}>
                <Footer />
              </Grid>
            ) : null}
          </Grid>
        )}
      </LocalizationProvider>
    </ThemeProvider>
  );
}

export default observer(App);
