#!/usr/bin/env node
/**
 * Auxis Data Manager
 * Usage:
 *   node tools/data-manager.js export          → export all data to exports/
 *   node tools/data-manager.js import          → import all data from exports/
 *   node tools/data-manager.js export users    → export only users
 *   node tools/data-manager.js import users    → import only users
 *   node tools/data-manager.js migrate-to-mongo → copy JSON files → MongoDB
 *   node tools/data-manager.js migrate-to-json  → copy MongoDB → JSON files
 */

require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });

const fs   = require('fs');
const path = require('path');

const DATA_DIR    = path.join(__dirname, '..', 'data');
const EXPORT_DIR  = path.join(__dirname, '..', 'exports');

const FILES = ['users', 'leave', 'reports', 'messages', 'salary', 'tests'];
const KEYS  = {
  users:    'users',
  leave:    'requests',
  reports:  'reports',
  messages: 'threads',
  salary:   'slips',
  tests:    'tests',
};

// ── Ensure dirs exist ─────────────────────────────────────────
[DATA_DIR, EXPORT_DIR].forEach(d => { if (!fs.existsSync(d)) fs.mkdirSync(d, { recursive: true }); });

const cmd    = process.argv[2] || 'help';
const target = process.argv[3] || 'all';

// ══════════════════════════════════════════════════════════════
// EXPORT  →  JSON files in exports/ folder
// ══════════════════════════════════════════════════════════════
function exportData() {
  const which = target === 'all' ? FILES : [target];
  let totalRecords = 0;

  console.log('\n📤 EXPORTING DATA\n' + '─'.repeat(40));
  which.forEach(name => {
    const src = path.join(DATA_DIR, `${name}.json`);
    if (!fs.existsSync(src)) { console.log(`  ⚠️  ${name}.json not found — skipping`); return; }

    const raw  = JSON.parse(fs.readFileSync(src, 'utf8'));
    const key  = KEYS[name];
    const rows = raw[key] || [];

    const outFile = path.join(EXPORT_DIR, `${name}_export_${timestamp()}.json`);
    fs.writeFileSync(outFile, JSON.stringify({ exported_at: new Date().toISOString(), collection: name, count: rows.length, data: rows }, null, 2));

    console.log(`  ✅  ${name.padEnd(10)} → ${rows.length} records  →  ${path.basename(outFile)}`);
    totalRecords += rows.length;
  });

  console.log('─'.repeat(40));
  console.log(`  Total: ${totalRecords} records exported to exports/\n`);
}

// ══════════════════════════════════════════════════════════════
// IMPORT  →  from exports/ back into data/
// ══════════════════════════════════════════════════════════════
function importData() {
  const which = target === 'all' ? FILES : [target];
  console.log('\n📥 IMPORTING DATA\n' + '─'.repeat(40));

  which.forEach(name => {
    // Find latest export file for this collection
    const exportFiles = fs.readdirSync(EXPORT_DIR)
      .filter(f => f.startsWith(`${name}_export_`) && f.endsWith('.json'))
      .sort()
      .reverse();

    if (!exportFiles.length) { console.log(`  ⚠️  No export file found for ${name} — skipping`); return; }

    const latest  = path.join(EXPORT_DIR, exportFiles[0]);
    const payload = JSON.parse(fs.readFileSync(latest, 'utf8'));
    const rows    = payload.data || [];
    const key     = KEYS[name];

    // Load existing data file (or create empty)
    const destFile = path.join(DATA_DIR, `${name}.json`);
    let existing = {};
    if (fs.existsSync(destFile)) existing = JSON.parse(fs.readFileSync(destFile, 'utf8'));
    existing[key] = rows;
    fs.writeFileSync(destFile, JSON.stringify(existing, null, 2));

    console.log(`  ✅  ${name.padEnd(10)} ← ${rows.length} records  ←  ${exportFiles[0]}`);
  });

  console.log('─'.repeat(40));
  console.log('  Import complete. Restart the server to use new data.\n');
}

// ══════════════════════════════════════════════════════════════
// BACKUP  →  single zip-like JSON snapshot
// ══════════════════════════════════════════════════════════════
function backupAll() {
  console.log('\n💾 CREATING FULL BACKUP\n' + '─'.repeat(40));
  const snapshot = { created_at: new Date().toISOString(), collections: {} };

  FILES.forEach(name => {
    const src = path.join(DATA_DIR, `${name}.json`);
    if (!fs.existsSync(src)) { snapshot.collections[name] = []; return; }
    const raw  = JSON.parse(fs.readFileSync(src, 'utf8'));
    snapshot.collections[name] = raw[KEYS[name]] || [];
    console.log(`  ✅  ${name.padEnd(10)} — ${snapshot.collections[name].length} records`);
  });

  const backupFile = path.join(EXPORT_DIR, `auxis_backup_${timestamp()}.json`);
  fs.writeFileSync(backupFile, JSON.stringify(snapshot, null, 2));
  const sizeKB = (fs.statSync(backupFile).size / 1024).toFixed(1);
  console.log('─'.repeat(40));
  console.log(`  Backup saved: ${path.basename(backupFile)}  (${sizeKB} KB)\n`);
}

// ══════════════════════════════════════════════════════════════
// RESTORE  →  from a full backup JSON
// ══════════════════════════════════════════════════════════════
function restoreBackup() {
  const backupFiles = fs.readdirSync(EXPORT_DIR)
    .filter(f => f.startsWith('auxis_backup_') && f.endsWith('.json'))
    .sort().reverse();

  if (!backupFiles.length) { console.log('\n⚠️  No backup file found in exports/\n'); return; }

  const latest   = path.join(EXPORT_DIR, backupFiles[0]);
  const snapshot = JSON.parse(fs.readFileSync(latest, 'utf8'));

  console.log(`\n🔁 RESTORING FROM: ${backupFiles[0]}\n` + '─'.repeat(40));
  FILES.forEach(name => {
    const rows    = (snapshot.collections || {})[name] || [];
    const key     = KEYS[name];
    const dest    = path.join(DATA_DIR, `${name}.json`);
    fs.writeFileSync(dest, JSON.stringify({ [key]: rows }, null, 2));
    console.log(`  ✅  ${name.padEnd(10)} — ${rows.length} records restored`);
  });

  console.log('─'.repeat(40));
  console.log('  Restore complete. Restart the server.\n');
}

// ══════════════════════════════════════════════════════════════
// MIGRATE JSON → MongoDB
// ══════════════════════════════════════════════════════════════
async function migrateToMongo() {
  const { connectDB } = require('../lib/mongoose');
  const { User, Leave, Report, Thread, Salary, Test, Result } = require('../models');

  console.log('\n🚀 MIGRATING JSON → MongoDB\n' + '─'.repeat(40));
  const ok = await connectDB();
  if (!ok) { console.log('❌ Cannot connect to MongoDB. Check MONGODB_URI in .env'); process.exit(1); }

  async function migrate(name, Model, transform) {
    const src = path.join(DATA_DIR, `${name}.json`);
    if (!fs.existsSync(src)) { console.log(`  ⚠️  ${name}.json not found`); return; }
    const raw  = JSON.parse(fs.readFileSync(src, 'utf8'));
    const rows = (raw[KEYS[name]] || []).map(transform || (r => r));
    if (!rows.length) { console.log(`  ⏭️  ${name.padEnd(10)} — no records`); return; }
    await Model.deleteMany({});
    await Model.insertMany(rows, { ordered: false }).catch(() => {});
    console.log(`  ✅  ${name.padEnd(10)} — ${rows.length} records migrated`);
  }

  await migrate('users',    User,   u  => ({ ...u, _id: undefined }));
  await migrate('leave',    Leave,  l  => ({ ...l, _id: undefined }));
  await migrate('reports',  Report, r  => ({ ...r, _id: undefined }));
  await migrate('messages', Thread, t  => ({ ...t, _id: undefined }));
  await migrate('salary',   Salary, s  => ({ ...s, _id: undefined }));
  await migrate('tests',    Test,   t  => ({ ...t, _id: undefined }));

  console.log('─'.repeat(40));
  console.log('  Migration complete! Your data is now in MongoDB Atlas.\n');
  process.exit(0);
}

// ══════════════════════════════════════════════════════════════
// MIGRATE MongoDB → JSON
// ══════════════════════════════════════════════════════════════
async function migrateToJSON() {
  const { connectDB } = require('../lib/mongoose');
  const { User, Leave, Report, Thread, Salary, Test, Result } = require('../models');

  console.log('\n📦 MIGRATING MongoDB → JSON\n' + '─'.repeat(40));
  const ok = await connectDB();
  if (!ok) { console.log('❌ Cannot connect to MongoDB. Check MONGODB_URI in .env'); process.exit(1); }

  async function dump(name, Model, key) {
    const rows = await Model.find({}).lean();
    const dest = path.join(DATA_DIR, `${name}.json`);
    fs.writeFileSync(dest, JSON.stringify({ [key]: rows }, null, 2));
    console.log(`  ✅  ${name.padEnd(10)} — ${rows.length} records saved to data/${name}.json`);
  }

  await dump('users',    User,   'users');
  await dump('leave',    Leave,  'requests');
  await dump('reports',  Report, 'reports');
  await dump('messages', Thread, 'threads');
  await dump('salary',   Salary, 'slips');
  await dump('tests',    Test,   'tests');

  console.log('─'.repeat(40));
  console.log('  Done! Your MongoDB data is now in local JSON files.\n');
  process.exit(0);
}

// ══════════════════════════════════════════════════════════════
// STATS  →  show record counts
// ══════════════════════════════════════════════════════════════
function showStats() {
  console.log('\n📊 DATABASE STATS (local JSON)\n' + '─'.repeat(40));
  let totalSize = 0;
  FILES.forEach(name => {
    const src = path.join(DATA_DIR, `${name}.json`);
    if (!fs.existsSync(src)) { console.log(`  ${name.padEnd(12)} — file not found`); return; }
    const raw   = JSON.parse(fs.readFileSync(src, 'utf8'));
    const rows  = (raw[KEYS[name]] || []).length;
    const bytes = fs.statSync(src).size;
    totalSize += bytes;
    console.log(`  ${name.padEnd(12)} ${String(rows).padStart(5)} records   ${(bytes/1024).toFixed(1).padStart(7)} KB`);
  });
  console.log('─'.repeat(40));
  console.log(`  Total size: ${(totalSize/1024).toFixed(1)} KB  (${(totalSize/1024/1024).toFixed(2)} MB)\n`);
}

// ── Helper ────────────────────────────────────────────────────
function timestamp() {
  return new Date().toISOString().replace(/[:.]/g,'-').slice(0,19);
}

function showHelp() {
  console.log(`
╔══════════════════════════════════════════════════════╗
║           Auxis Data Manager — Commands              ║
╠══════════════════════════════════════════════════════╣
║  node tools/data-manager.js export                   ║
║    → Export all collections to exports/ folder       ║
║                                                      ║
║  node tools/data-manager.js export users             ║
║    → Export only users collection                    ║
║                                                      ║
║  node tools/data-manager.js import                   ║
║    → Import all from latest export files             ║
║                                                      ║
║  node tools/data-manager.js import leave             ║
║    → Import only leave collection                    ║
║                                                      ║
║  node tools/data-manager.js backup                   ║
║    → Create single full backup snapshot              ║
║                                                      ║
║  node tools/data-manager.js restore                  ║
║    → Restore from latest backup snapshot             ║
║                                                      ║
║  node tools/data-manager.js stats                    ║
║    → Show record counts & file sizes                 ║
║                                                      ║
║  node tools/data-manager.js migrate-to-mongo         ║
║    → Copy all JSON data → MongoDB Atlas              ║
║                                                      ║
║  node tools/data-manager.js migrate-to-json          ║
║    → Copy MongoDB Atlas data → local JSON files      ║
╚══════════════════════════════════════════════════════╝
`);
}

// ── Router ────────────────────────────────────────────────────
switch (cmd) {
  case 'export':           exportData();           break;
  case 'import':           importData();           break;
  case 'backup':           backupAll();            break;
  case 'restore':          restoreBackup();        break;
  case 'stats':            showStats();            break;
  case 'migrate-to-mongo': migrateToMongo();       break;
  case 'migrate-to-json':  migrateToJSON();        break;
  default:                 showHelp();             break;
}
