// ============================================================
// PHONE EXTENSIONS / PAGERS — per-user personal directory
// ============================================================
// Soft-delete via trashed_at: deleting moves to trash; user can restore
// or purge. List supports async search (q) and trash toggle (trash=1).

var express = require('express');
var multer = require('multer');
var router = express.Router();
var db = require('../db/database');
var { authMiddleware } = require('../middleware/auth');
var logger = require('../utils/logger');
var transfer = require('../utils/extensionTransfer');

var upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 1024 * 1024 } });

router.use(authMiddleware);

function sanitizeType(t) {
  return transfer.sanitizeType(t);
}
function clip(s, n) {
  return transfer.clip(s, n);
}
function parseId(raw) {
  var n = parseInt(raw, 10);
  return (Number.isFinite(n) && n > 0) ? n : null;
}
// ── GET /api/extensions ─────────────────────────────────────
// Query params:
//   trash=1   → return trashed items only (default: active only)
//   q=text    → case-insensitive substring search on location/name/number/notes
router.get('/extensions', async function (req, res) {
  try {
    var trashMode = req.query.trash === '1' || req.query.trash === 'true';
    var q = (req.query.q || '').trim();

    var sql =
      'SELECT id, location, name, number, type, notes, trashed_at, created_at, updated_at ' +
      'FROM user_phone_extensions WHERE user_id = $1 AND trashed_at IS ' +
      (trashMode ? 'NOT NULL' : 'NULL');
    var params = [req.user.id];

    if (q) {
      sql += ' AND (LOWER(location) LIKE $2 OR LOWER(name) LIKE $2 OR LOWER(number) LIKE $2 OR LOWER(notes) LIKE $2)';
      params.push('%' + q.toLowerCase() + '%');
    }
    sql += ' ORDER BY location ASC, type ASC, name ASC';

    var rows = await db.all(sql, params);
    res.json({ success: true, items: rows });
  } catch (e) {
    logger.error('GET /extensions', e.message);
    res.status(500).json({ error: 'Request failed' });
  }
});

// ── GET /api/extensions/export — ZIP export for sharing/import ─────────
router.get('/extensions/export', async function (req, res) {
  try {
    var rows = await db.all(
      'SELECT location, name, number, type, notes FROM user_phone_extensions WHERE user_id = $1 AND trashed_at IS NULL ORDER BY location ASC, type ASC, name ASC',
      [req.user.id]
    );
    var payload = transfer.exportPayload(rows);
    var zip = transfer.createJsonZip('pedscribe-extensions.json', payload);
    res.setHeader('Content-Type', 'application/zip');
    res.setHeader('Content-Disposition', 'attachment; filename="pedscribe-extensions.zip"');
    res.setHeader('X-Export-Count', String(payload.items.length));
    res.send(zip);
  } catch (e) {
    logger.error('GET /extensions/export', e.message);
    res.status(500).json({ error: 'Export failed' });
  }
});

// ── POST /api/extensions/import/preview — preview another user's JSON export
router.post('/extensions/import/preview', async function (req, res) {
  try {
    var items = transfer.importItemsFromBody(req.body);
    if (!items.length) return res.status(400).json({ error: 'No valid entries to import' });
    var analysis = await analyzeImportForUser(req.user.id, items);
    res.json({ success: true, preview: analysis });
  } catch (e) {
    logger.error('POST /extensions/import/preview', e.message);
    res.status(500).json({ error: 'Import preview failed' });
  }
});

// ── POST /api/extensions/import — import another user's JSON export ─────
router.post('/extensions/import', async function (req, res) {
  try {
    var items = transfer.importItemsFromBody(req.body);
    var result = await importItemsForUser(req.user.id, items, parseImportOptions(req.body && req.body.options));
    if (!result.success) return res.status(400).json(result);
    res.json(result);
  } catch (e) {
    logger.error('POST /extensions/import', e.message);
    res.status(500).json({ error: 'Import failed' });
  }
});

// ── POST /api/extensions/import-file/preview — preview JSON or ZIP file ─
router.post('/extensions/import-file/preview', upload.single('file'), async function (req, res) {
  try {
    if (!req.file || !req.file.buffer) return res.status(400).json({ error: 'Import file is required' });
    var parsed = transfer.parseImportBuffer(req.file.buffer);
    var items = transfer.importItemsFromBody(parsed);
    if (!items.length) return res.status(400).json({ error: 'No valid entries to import' });
    var analysis = await analyzeImportForUser(req.user.id, items);
    res.json({ success: true, preview: analysis });
  } catch (e) {
    logger.error('POST /extensions/import-file/preview', e.message);
    res.status(400).json({ error: 'Import file must be a valid PedScribe JSON or ZIP export' });
  }
});

// ── POST /api/extensions/import-file — import JSON or ZIP file ─────────
router.post('/extensions/import-file', upload.single('file'), async function (req, res) {
  try {
    if (!req.file || !req.file.buffer) return res.status(400).json({ error: 'Import file is required' });
    var parsed = transfer.parseImportBuffer(req.file.buffer);
    var items = transfer.importItemsFromBody(parsed);
    var result = await importItemsForUser(req.user.id, items, parseImportOptions(req.body));
    if (!result.success) return res.status(400).json(result);
    res.json(result);
  } catch (e) {
    logger.error('POST /extensions/import-file', e.message);
    res.status(400).json({ error: 'Import file must be a valid PedScribe JSON or ZIP export' });
  }
});

function parseImportOptions(raw) {
  raw = raw || {};
  return {
    importPossibleDuplicates: raw.importPossibleDuplicates === true || raw.importPossibleDuplicates === 'true' || raw.importPossibleDuplicates === '1',
    restoreTrashed: raw.restoreTrashed === true || raw.restoreTrashed === 'true' || raw.restoreTrashed === '1'
  };
}

async function getExistingRows(userId) {
  return db.all(
    'SELECT id, location, name, number, type, notes, trashed_at FROM user_phone_extensions WHERE user_id = $1',
    [userId]
  );
}

async function analyzeImportForUser(userId, items) {
  var existingRows = await getExistingRows(userId);
  return transfer.analyzeImport(items, existingRows);
}

async function importItemsForUser(userId, items, options) {
  if (!items.length) return { success: false, error: 'No valid entries to import' };
  options = options || {};

  var existingRows = await getExistingRows(userId);
  var analysis = transfer.analyzeImport(items, existingRows);

  var imported = 0;
  var skipped = 0;
  var restored = 0;
  var possibleSkipped = 0;
  for (var i = 0; i < analysis.entries.length; i++) {
    var entry = analysis.entries[i];
    var item = entry.item;
    if (entry.status === 'exact_active') {
      skipped++;
      continue;
    }
    if (entry.status === 'exact_trashed') {
      if (options.restoreTrashed && entry.exactMatch && entry.exactMatch.id) {
        await db.run(
          'UPDATE user_phone_extensions SET trashed_at = NULL, updated_at = NOW() WHERE id = $1 AND user_id = $2 AND trashed_at IS NOT NULL',
          [entry.exactMatch.id, userId]
        );
        restored++;
      } else {
        skipped++;
      }
      continue;
    }
    if (entry.status === 'possible_duplicate' && !options.importPossibleDuplicates) {
      skipped++;
      possibleSkipped++;
      continue;
    }
    await db.run(
      'INSERT INTO user_phone_extensions (user_id, location, name, number, type, notes) VALUES ($1,$2,$3,$4,$5,$6)',
      [userId, item.location, item.name, item.number, item.type, item.notes]
    );
    imported++;
  }

  return { success: true, imported: imported, restored: restored, skipped: skipped, possibleSkipped: possibleSkipped, total: items.length, preview: analysis.summary };
}

// ── POST /api/extensions ────────────────────────────────────
router.post('/extensions', async function (req, res) {
  try {
    var location = clip(req.body.location, 120);
    var name     = clip(req.body.name, 120);
    var number   = clip(req.body.number, 40);
    var type     = sanitizeType(req.body.type);
    var notes    = clip(req.body.notes, 500);
    if (!location) return res.status(400).json({ error: 'Location is required' });
    if (!name)     return res.status(400).json({ error: 'Name / department is required' });
    if (!number)   return res.status(400).json({ error: 'Number is required' });

    var result = await db.run(
      'INSERT INTO user_phone_extensions (user_id, location, name, number, type, notes) VALUES ($1,$2,$3,$4,$5,$6)',
      [req.user.id, location, name, number, type, notes]
    );
    res.json({ success: true, id: result.lastInsertRowid });
  } catch (e) {
    logger.error('POST /extensions', e.message);
    res.status(500).json({ error: 'Request failed' });
  }
});

// ── PUT /api/extensions/:id ─────────────────────────────────
router.put('/extensions/:id', async function (req, res) {
  try {
    var id = parseId(req.params.id);
    if (!id) return res.status(400).json({ error: 'Invalid id' });
    var location = clip(req.body.location, 120);
    var name     = clip(req.body.name, 120);
    var number   = clip(req.body.number, 40);
    var type     = sanitizeType(req.body.type);
    var notes    = clip(req.body.notes, 500);
    if (!location || !name || !number) return res.status(400).json({ error: 'Location, name, and number are required' });

    var result = await db.run(
      'UPDATE user_phone_extensions SET location=$1, name=$2, number=$3, type=$4, notes=$5, updated_at=NOW() WHERE id=$6 AND user_id=$7',
      [location, name, number, type, notes, id, req.user.id]
    );
    if (result.changes === 0) return res.status(404).json({ error: 'Not found' });
    res.json({ success: true });
  } catch (e) {
    logger.error('PUT /extensions/:id', e.message);
    res.status(500).json({ error: 'Request failed' });
  }
});

// ── DELETE /api/extensions/:id — soft-delete (move to trash) ──
router.delete('/extensions/:id', async function (req, res) {
  try {
    var id = parseId(req.params.id);
    if (!id) return res.status(400).json({ error: 'Invalid id' });
    var result = await db.run(
      'UPDATE user_phone_extensions SET trashed_at = NOW(), updated_at = NOW() WHERE id=$1 AND user_id=$2 AND trashed_at IS NULL',
      [id, req.user.id]
    );
    if (result.changes === 0) return res.status(404).json({ error: 'Not found or already trashed' });
    res.json({ success: true });
  } catch (e) {
    logger.error('DELETE /extensions/:id', e.message);
    res.status(500).json({ error: 'Request failed' });
  }
});

// ── POST /api/extensions/:id/restore — bring back from trash ──
router.post('/extensions/:id/restore', async function (req, res) {
  try {
    var id = parseId(req.params.id);
    if (!id) return res.status(400).json({ error: 'Invalid id' });
    var result = await db.run(
      'UPDATE user_phone_extensions SET trashed_at = NULL, updated_at = NOW() WHERE id=$1 AND user_id=$2 AND trashed_at IS NOT NULL',
      [id, req.user.id]
    );
    if (result.changes === 0) return res.status(404).json({ error: 'Not found in trash' });
    res.json({ success: true });
  } catch (e) {
    logger.error('POST /extensions/:id/restore', e.message);
    res.status(500).json({ error: 'Request failed' });
  }
});

// ── DELETE /api/extensions/:id/purge — hard delete (only from trash) ──
router.delete('/extensions/:id/purge', async function (req, res) {
  try {
    var id = parseId(req.params.id);
    if (!id) return res.status(400).json({ error: 'Invalid id' });
    var result = await db.run(
      'DELETE FROM user_phone_extensions WHERE id=$1 AND user_id=$2 AND trashed_at IS NOT NULL',
      [id, req.user.id]
    );
    if (result.changes === 0) return res.status(404).json({ error: 'Must trash before purge' });
    res.json({ success: true });
  } catch (e) {
    logger.error('DELETE /extensions/:id/purge', e.message);
    res.status(500).json({ error: 'Request failed' });
  }
});

module.exports = router;
module.exports._test = { importItemsForUser, analyzeImportForUser, parseImportOptions };
