import {
  ActionTrackingResult,
  applySerializedActionAndSyncNewModelIds,
  applySnapshot,
  fromSnapshot,
  frozen,
  getSnapshot,
  model,
  Model,
  ModelAutoTypeCheckingMode,
  onActionMiddleware,
  registerRootStore,
  serializeActionCall,
  SerializedActionCallWithModelIdOverrides,
  setGlobalConfig,
  tProp,
  types,
  getRootStore as getStore,
  unregisterRootStore,
  modelFlow,
  _async,
  _await,
} from 'mobx-keystone';
import { reaction } from 'mobx';
import TicketList from './Application/TicketList';
import Basket from './Application/Basket';
import UserList from './Application/UserList';
import Settings from './Settings/Settings';
import TemplateList from './Application/TemplateList';
import TarifList from './Application/TarifList';
import ScannedTicketList from './Application/ScannedTicketList';
import Ui from './Ui/Ui';
import Logs from './Logs/Logs';
import Acs01List from './Remote/Acs01List';
import CounterList from './Remote/CounterList';
import ReportsList from './Reports/ReportsList';
import Terminal from './Settings/Terminal';
import PassageList from './Remote/Acs01/PassageList';
import AuxList from './Remote/Acs01/AuxList';
import PrinterList from './Remote/Acs01/PrinterList';
import ReaderList from './Remote/Acs01/ReaderList';
import Layout from './Settings/Layout';
import ScenarioList from './Remote/Acs01/ScenarioList';
import LanguageList from './Languages/LanguageList';
import Server from './server';
import Template from './Application/Template';
import fs from 'fs';
import path from 'path';
import os from 'os';

setGlobalConfig({
  modelAutoTypeChecking: ModelAutoTypeCheckingMode.AlwaysOn,
});

// Define file storage location in AppData\Local
const configPath = path.join(os.homedir(), "AppData", "Local", "came-access", "config.json");

// Ensure the directory exists
const configDir = path.dirname(configPath);
if (!fs.existsSync(configDir)) {
  fs.mkdirSync(configDir, { recursive: true });
}

// eslint-disable-next-line no-use-before-define
let rootStore: RootStore;
@model('keystone/RootStore')
export class RootStore extends Model({
  ticketList: tProp(types.model<TicketList>(TicketList)),
  basket: tProp(types.model<Basket>(Basket)),
  userList: tProp(types.model<UserList>(UserList)),
  settings: tProp(types.model<Settings>(Settings)),
  terminal: tProp(types.model<Terminal>(Terminal)),
  tarifList: tProp(types.model<TarifList>(TarifList)),
  templateList: tProp(types.model<TemplateList>(TemplateList)),
  scannedTicketList: tProp(types.model<ScannedTicketList>(ScannedTicketList)),
  ui: tProp(types.model<Ui>(Ui)),
  logs: tProp(types.model<Logs>(Logs)),
  acs01List: tProp(types.model<Acs01List>(Acs01List)),
  counterList: tProp(types.model<CounterList>(CounterList)),
  reportsList: tProp(types.model<ReportsList>(ReportsList)),
  passageList: tProp(types.model<PassageList>(PassageList)),
  auxList: tProp(types.model<AuxList>(AuxList)),
  printerList: tProp(types.model<PrinterList>(PrinterList)),
  readerList: tProp(types.model<ReaderList>(ReaderList)),
  layout: tProp(types.model<Layout>(Layout)),
  scenarioList: tProp(types.model<ScenarioList>(ScenarioList)),
  languageList: tProp(types.model<LanguageList>(LanguageList)),
}) {
  onAttachedToRootStore() {
    const reactionDisposer = reaction(
      () => {
        // Take the full snapshot
        const sn = getSnapshot(this) as any;
  
        // Replace scannedTicketList with an empty model snapshot before saving
        try {
          sn.scannedTicketList = getSnapshot(new ScannedTicketList({}));
        } catch {
          // If ScannedTicketList constructor throws for any reason, fall back to empty object
          sn.scannedTicketList = {};
        }
  
        return sn;
      },
      (sn) => {
        try {
          localStorage.setItem('newst', JSON.stringify(sn));
        } catch (e) {
          console.warn('Persist failed:', e);
        }
      },
      { fireImmediately: true }
    );
  
    return () => reactionDisposer();
  }
  

  get all() {
    return this;
  }
}

export async function createRootStore() {
  const rawStored = localStorage.getItem('newst');
  if (typeof rawStored === 'string') {

    try {

      const savedRootStore = await JSON.parse(rawStored);
      rootStore = fromSnapshot<RootStore>(savedRootStore);
      registerRootStore(rootStore);
    } catch (e) {
      console.log('There was an error restoring the initial localStorage');
    }
  } else {
    try {
      rootStore = new RootStore({
        ticketList: new TicketList({}),
        basket: new Basket({}),
        userList: new UserList({}),
        settings: new Settings({}),
        terminal: new Terminal({}),
        tarifList: new TarifList({}),
        templateList: new TemplateList({}),
        scannedTicketList: new ScannedTicketList({}),
        ui: new Ui({}),
        logs: new Logs({}),
        acs01List: new Acs01List({}),
        counterList: new CounterList({}),
        reportsList: new ReportsList({}),
        passageList: new PassageList({}),
        auxList: new AuxList({}),
        printerList: new PrinterList({}),
        readerList: new ReaderList({}),
        layout: new Layout({}),
        scenarioList: new ScenarioList({}),
        languageList: new LanguageList({}),
      });
    } catch (e) {
      console.log('There was an error $', e);
    }

    // Now we will link the preconfigured tarif and template
    const initialIdTarif = rootStore.tarifList.all[0].id;
    if (rootStore.templateList.all.length === 0) {
      rootStore.templateList.add(
        new Template({
          name: 'default',
          idTemplate: '7860',
          idTarif: initialIdTarif || '',
        })
      );
    }
    registerRootStore(rootStore);
  }

  return rootStore;
}

export function getRootStore() {
  return rootStore;
}

export async function getRootStoreAsync() {
  return rootStore;
}

(async () => {
  const st = await createRootStore();
  return console.log('1. CREATED rootStore');
})();
