const { app, BrowserWindow, dialog, ipcMain, shell, Menu } = require('electron');
const path = require('path');
const fs = require('fs-extra');

const { processFolder } = require('./services/folderProcessor');
const { processZip } = require('./services/zipProcessor');
const {
  resolveUnroutedDir,
  listUnroutedFiles,
  listDuplicateFiles,
  listSkippedFiles,
  clearUnroutedFiles,
  clearDuplicateFiles,
  clearSkippedFiles,
} = require('./services/unrouted');

const CAD_EXTENSIONS = ['prt', 'asm', 'drw'];
const DEFAULT_DESTINATION = 'X:\\';
const SETTINGS_FILENAME = 'cad-router-settings.json';
const LINUX_RUNTIME_DIR = '.cadroute';

function buildConfig(destination) {
  const resolvedDestination = String(destination || '').trim() || DEFAULT_DESTINATION;
  return {
    destination: resolvedDestination,
    rules: CAD_EXTENSIONS.map((ext) => ({ ext, destination: resolvedDestination })),
  };
}

function getSettingsPath() {
  return path.join(getRuntimeDirectory(), SETTINGS_FILENAME);
}

function getRuntimeDirectory() {
  if (process.platform === 'linux') {
    return path.join(app.getPath('home'), LINUX_RUNTIME_DIR);
  }

  return app.getPath('userData');
}

async function ensureRuntimeDirectory() {
  await fs.ensureDir(getRuntimeDirectory());
}

async function loadPersistedDestination() {
  try {
    const settingsPath = getSettingsPath();
    if (!(await fs.pathExists(settingsPath))) {
      return DEFAULT_DESTINATION;
    }

    const settings = await fs.readJson(settingsPath);
    const destination = String(settings?.destination || '').trim();
    return destination || DEFAULT_DESTINATION;
  } catch {
    return DEFAULT_DESTINATION;
  }
}

async function persistDestination(destination) {
  const settingsPath = getSettingsPath();
  await fs.ensureDir(path.dirname(settingsPath));
  await fs.writeJson(settingsPath, { destination }, { spaces: 2 });
}

let config = buildConfig(DEFAULT_DESTINATION);

function createWindow() {
  const win = new BrowserWindow({
    width: 1000,
    height: 800,
    icon: path.join(__dirname, 'build', 'icon.png'),
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
    },
  });

  win.loadFile(path.join(__dirname, 'renderer', 'index.html'));
}

function createDocsWindow() {
  const docs = new BrowserWindow({
    width: 900,
    height: 700,
    title: 'CadRoute — Documentazione',
    icon: path.join(__dirname, 'build', 'icon.png'),
    webPreferences: { contextIsolation: true, nodeIntegration: false },
  });
  docs.loadFile(path.join(__dirname, 'renderer', 'docs', 'index.html'));
  docs.setMenuBarVisibility(false);
}

function showAboutDialog() {
  dialog.showMessageBox({
    type: 'info',
    title: 'Informazioni su CadRoute',
    message: 'CadRoute',
    detail: [
      `Versione: ${app.getVersion()}`,
      `Autore: Davide Grilli`,
      `Azienda: Cevolani Italia s.r.l.`,
      `Licenza: MIT`,
      ``,
      `Smistatore automatico di file CAD (Creo).`,
      ``,
      `Electron: ${process.versions.electron}`,
      `Node: ${process.versions.node}`,
    ].join('\n'),
    buttons: ['OK'],
    noLink: true,
  });
}

Menu.setApplicationMenu(Menu.buildFromTemplate([
  {
    label: 'Informazioni',
    submenu: [{ label: 'Informazioni su CadRoute...', click: () => showAboutDialog() }],
  },
  {
    label: 'Help',
    submenu: [{ label: 'Documentazione', click: () => createDocsWindow() }],
  },
]));

app.whenReady().then(async () => {
  await ensureRuntimeDirectory();
  const persistedDestination = await loadPersistedDestination();
  config = buildConfig(persistedDestination);
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

ipcMain.handle('select-folder', async (event) => {
  const result = await dialog.showOpenDialog({
    properties: ['openDirectory'],
  });

  if (result.canceled || !result.filePaths[0]) {
    return { canceled: true };
  }

  const onProgress = (data) => event.sender.send('progress', data);
  const routingResult = await processFolder(result.filePaths[0], config, onProgress);
  return { canceled: false, ...routingResult };
});

ipcMain.handle('select-zip', async (event) => {
  const result = await dialog.showOpenDialog({
    properties: ['openFile'],
    filters: [{ name: 'Zip', extensions: ['zip'] }],
  });

  if (result.canceled || !result.filePaths[0]) {
    return { canceled: true };
  }

  const onProgress = (data) => event.sender.send('progress', data);
  const routingResult = await processZip(result.filePaths[0], config, onProgress);
  return { canceled: false, ...routingResult };
});

ipcMain.handle('process-dropped-path', async (event, payload) => {
  const droppedPath = String(payload?.path || '').trim();
  if (!droppedPath) {
    throw new Error('Percorso non valido');
  }

  const stats = await fs.stat(droppedPath).catch(() => null);
  if (!stats) {
    throw new Error('Percorso non trovato');
  }

  const onProgress = (data) => event.sender.send('progress', data);

  if (stats.isDirectory()) {
    const routingResult = await processFolder(droppedPath, config, onProgress);
    return { canceled: false, sourceType: 'folder', ...routingResult };
  }

  if (stats.isFile() && path.extname(droppedPath).toLowerCase() === '.zip') {
    const routingResult = await processZip(droppedPath, config, onProgress);
    return { canceled: false, sourceType: 'zip', ...routingResult };
  }

  throw new Error('Trascina una cartella o un file .zip');
});

ipcMain.handle('get-destination', async () => ({
  destination: config.destination || DEFAULT_DESTINATION,
}));

ipcMain.handle('select-destination-folder', async () => {
  const result = await dialog.showOpenDialog({
    properties: ['openDirectory'],
  });

  if (result.canceled || !result.filePaths[0]) {
    return { canceled: true };
  }

  return {
    canceled: false,
    path: result.filePaths[0],
  };
});

ipcMain.handle('update-destination', async (_event, payload) => {
  const destination = String(payload?.destination || '').trim();
  if (!destination) {
    throw new Error('La destinazione non puo essere vuota');
  }

  config = buildConfig(destination);
  await persistDestination(config.destination);
  return { destination: config.destination };
});


ipcMain.handle('open-unrouted-folder', async () => {
  const unroutedDir = await resolveUnroutedDir();
  const openResult = await shell.openPath(unroutedDir);

  if (openResult) {
    throw new Error(`Impossibile aprire la cartella: ${openResult}`);
  }

  return { path: unroutedDir };
});

ipcMain.handle('list-unrouted-files', async () => listUnroutedFiles());
ipcMain.handle('list-duplicates-files', async () => listDuplicateFiles());
ipcMain.handle('list-skipped-files', async () => listSkippedFiles());
ipcMain.handle('clear-unrouted-files', async () => clearUnroutedFiles());
ipcMain.handle('clear-duplicates-files', async () => clearDuplicateFiles());
ipcMain.handle('clear-skipped-files', async () => clearSkippedFiles());
