import { Router } from 'express';
import multer from 'multer';
import xlsx from 'xlsx';
import path from 'node:path';
import fs from 'node:fs';
import db from '../db/index.js';
import { HttpError } from '../middleware/errorHandler.js';

const UPLOAD_DIR = process.env.UPLOAD_DIR || path.resolve('./uploads');
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
const upload = multer({ dest: UPLOAD_DIR, limits: { fileSize: 5 * 1024 * 1024 } });

const router = Router();

/* ── GET /api/garanties ──────────────────────────────────────── */
router.get('/', (req, res) => {
  const rows = db.prepare(
    'SELECT * FROM garantie_types WHERE user_id = ? ORDER BY ordre, id'
  ).all(req.user.id);
  res.json(rows);
});

/* ── POST /api/garanties ─────────────────────────────────────── */
router.post('/', (req, res, next) => {
  try {
    const { libelle, description, ordre } = req.body || {};
    if (!libelle?.trim()) throw new HttpError(400, 'libelle est requis');
    const r = db.prepare(
      'INSERT INTO garantie_types (user_id, libelle, description, ordre) VALUES (?,?,?,?)'
    ).run(req.user.id, libelle.trim(), description?.trim() || null, Number(ordre ?? 0));
    res.status(201).json(db.prepare('SELECT * FROM garantie_types WHERE id = ?').get(r.lastInsertRowid));
  } catch (e) { next(e); }
});

/* ── PUT /api/garanties/:id ──────────────────────────────────── */
router.put('/:id', (req, res, next) => {
  try {
    const row = db.prepare('SELECT id FROM garantie_types WHERE id = ? AND user_id = ?')
      .get(req.params.id, req.user.id);
    if (!row) throw new HttpError(404, 'Garantie introuvable');
    const { libelle, description, ordre } = req.body || {};
    if (!libelle?.trim()) throw new HttpError(400, 'libelle est requis');
    db.prepare(
      'UPDATE garantie_types SET libelle=?, description=?, ordre=? WHERE id=?'
    ).run(libelle.trim(), description?.trim() || null, Number(ordre ?? 0), req.params.id);
    res.json(db.prepare('SELECT * FROM garantie_types WHERE id = ?').get(req.params.id));
  } catch (e) { next(e); }
});

/* ── DELETE /api/garanties/:id ───────────────────────────────── */
router.delete('/:id', (req, res, next) => {
  try {
    const row = db.prepare('SELECT id FROM garantie_types WHERE id = ? AND user_id = ?')
      .get(req.params.id, req.user.id);
    if (!row) throw new HttpError(404, 'Garantie introuvable');
    db.prepare('DELETE FROM garantie_types WHERE id = ?').run(req.params.id);
    res.json({ deleted: true });
  } catch (e) { next(e); }
});

/* ── POST /api/garanties/import  ─────────────────────────────────
   Accepte un fichier .xlsx / .csv / .json
   Colonnes reconnues : libelle (obligatoire), description, ordre
   Comportement : upsert sur libelle (insensible à la casse)
   ─────────────────────────────────────────────────────────────── */
router.post('/import', upload.single('file'), (req, res, next) => {
  try {
    if (!req.file) throw new HttpError(400, 'Aucun fichier reçu');

    const ext = path.extname(req.file.originalname).toLowerCase();
    let rows;

    if (ext === '.json') {
      const content = fs.readFileSync(req.file.path, 'utf8');
      let parsed;
      try { parsed = JSON.parse(content); } catch {
        throw new HttpError(400, 'Fichier JSON invalide');
      }
      rows = Array.isArray(parsed) ? parsed
           : Array.isArray(parsed?.garanties) ? parsed.garanties
           : null;
      if (!rows) throw new HttpError(400, 'Le JSON doit être un tableau ou contenir une clé "garanties"');
    } else {
      const wb = xlsx.readFile(req.file.path, { cellDates: true });
      const ws = wb.Sheets[wb.SheetNames[0]];
      rows = xlsx.utils.sheet_to_json(ws, { defval: null, raw: false });
    }

    try { fs.unlinkSync(req.file.path); } catch { /* noop */ }

    if (!rows.length) return res.json({ inserted: 0, updated: 0, skipped: 0, errors: [] });

    // Normalise les clés (insensible à la casse et aux espaces)
    const norm = (obj) => {
      const out = {};
      for (const [k, v] of Object.entries(obj)) out[k.toLowerCase().trim()] = v;
      return out;
    };

    let inserted = 0, updated = 0, skipped = 0;
    const errors = [];

    const tx = db.transaction(() => {
      for (let i = 0; i < rows.length; i++) {
        const r = norm(rows[i]);
        const libelle = String(r.libelle ?? r['libellé'] ?? r.label ?? '').trim();
        if (!libelle) { skipped++; errors.push({ row: i + 2, error: 'libelle vide — ligne ignorée' }); continue; }

        const description = String(r.description ?? r.desc ?? '').trim() || null;
        const ordre       = parseInt(r.ordre ?? r.order ?? 0, 10) || 0;

        const existing = db.prepare(
          'SELECT id FROM garantie_types WHERE user_id = ? AND LOWER(libelle) = LOWER(?)'
        ).get(req.user.id, libelle);

        if (existing) {
          db.prepare(
            'UPDATE garantie_types SET description=?, ordre=? WHERE id=?'
          ).run(description, ordre, existing.id);
          updated++;
        } else {
          db.prepare(
            'INSERT INTO garantie_types (user_id, libelle, description, ordre) VALUES (?,?,?,?)'
          ).run(req.user.id, libelle, description, ordre);
          inserted++;
        }
      }
    });
    tx();

    res.json({ inserted, updated, skipped, total: rows.length, errors: errors.slice(0, 20) });
  } catch (e) { next(e); }
});

export default router;
