/**
 * autoExport.js — Job planifié à 3h00 du matin.
 * Génère un export complet (DB + assets) et le conserve dans DATA_DIR/exports/.
 * Résultat tracé dans job_logs (job_name = 'auto_export').
 */

import fs   from 'node:fs';
import path from 'node:path';
import os   from 'node:os';
import { fileURLToPath } from 'node:url';
import db         from '../db/index.js';
import { createZip } from '../utils/zip.js';

const __dirname  = path.dirname(fileURLToPath(import.meta.url));
const dataDir    = process.env.DATA_DIR
  ? path.resolve(process.env.DATA_DIR)
  : path.resolve(__dirname, '../../../data');
const exportsDir = path.join(dataDir, 'exports');
const MAX_EXPORTS = 10;
const JOB_NAME   = 'auto_export';

function writeLog({ status, nbChanges = 0, details = null, errorMsg = null }) {
  try {
    db.prepare(`
      INSERT INTO job_logs (job_name, status, nb_changes, details, error_msg)
      VALUES (?, ?, ?, ?, ?)
    `).run(JOB_NAME, status, nbChanges, details, errorMsg);
  } catch (e) {
    console.error('[autoExport] Impossible d\'écrire dans job_logs :', e.message);
  }
}

function purgeOldExports() {
  try {
    fs.mkdirSync(exportsDir, { recursive: true });
    const files = fs.readdirSync(exportsDir)
      .filter(f => f.endsWith('.zip'))
      .map(f => ({ f, mtime: fs.statSync(path.join(exportsDir, f)).mtimeMs }))
      .sort((a, b) => b.mtime - a.mtime);
    for (const { f } of files.slice(MAX_EXPORTS)) {
      fs.unlinkSync(path.join(exportsDir, f));
    }
  } catch (e) {
    console.error('[autoExport] Erreur purge :', e.message);
  }
}

export async function runAutoExport() {
  const tmpDb = path.join(os.tmpdir(), `cl-auto-export-${Date.now()}.db`);
  const startedAt = Date.now();
  console.log('[autoExport] Démarrage de l\'export automatique…');

  try {
    db.exec(`VACUUM INTO '${tmpDb.replace(/'/g, "''")}'`);
    const dbData = fs.readFileSync(tmpDb);

    const now = new Date();
    const pad = n => String(n).padStart(2, '0');
    const ts  = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`
              + `_${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
    const filename = `crowdlending-export-${ts}.zip`;

    const entries = [];
    entries.push({
      name: 'manifest.json',
      data: JSON.stringify({
        version: '1.0', app: 'crowdlending',
        exported_at: now.toISOString(),
        type: 'full-export',
        source: 'auto_export_job',
      }, null, 2),
    });
    entries.push({ name: 'crowdlending.db', data: dbData });

    let assetCount = 0;
    for (const subdir of ['logos', 'icons']) {
      const dir = path.join(dataDir, subdir);
      if (!fs.existsSync(dir)) continue;
      for (const f of fs.readdirSync(dir)) {
        const fpath = path.join(dir, f);
        if (fs.statSync(fpath).isFile()) {
          entries.push({ name: `${subdir}/${f}`, data: fs.readFileSync(fpath) });
          assetCount++;
        }
      }
    }

    const zipBuf = createZip(entries);
    fs.mkdirSync(exportsDir, { recursive: true });
    fs.writeFileSync(path.join(exportsDir, filename), zipBuf);
    purgeOldExports();

    const elapsed = ((Date.now() - startedAt) / 1000).toFixed(1);
    const details = `Fichier : ${filename} | Taille : ${(zipBuf.length / 1024).toFixed(0)} Ko | Assets : ${assetCount} | Durée : ${elapsed}s`;
    writeLog({ status: 'ok', nbChanges: 1, details });
    console.log(`[autoExport] Export terminé en ${elapsed}s → ${filename}`);
  } catch (e) {
    console.error('[autoExport] Erreur :', e.message);
    writeLog({ status: 'error', nbChanges: 0, errorMsg: e.message });
  } finally {
    if (fs.existsSync(tmpDb)) fs.unlinkSync(tmpDb);
  }
}

/** Planifie runAutoExport() tous les jours à 3h00 locale (sans dérive). */
export function startAutoExportJob() {
  function msUntil3am() {
    const now  = new Date();
    const next = new Date(now);
    next.setHours(3, 0, 0, 0);
    if (next <= now) next.setDate(next.getDate() + 1);
    return next.getTime() - now.getTime();
  }

  function scheduleDailyRun() {
    const delay = msUntil3am();
    setTimeout(async () => {
      await runAutoExport();
      scheduleDailyRun();
    }, delay);
  }

  scheduleDailyRun();
  console.log(`[autoExport] Job planifié — prochaine exécution dans ${Math.round(msUntil3am() / 60000)} min (3h00)`);
}
