import { randomUUID } from 'crypto';
import { Router } from 'express';
import db from '../db.js';
import { loadIntegrations } from '../integrations.js';
import { authenticateLdap } from '../ldap-auth.js';
import { badRequest } from '../lib/http.js';
import { hashPassword, verifyPassword } from '../password.js';

const router = Router();

function userPayload(row) {
  if (!row) return null;
  const role = row.role;
  const canAdmin = role === 'admin';
  const canEditCrm = canAdmin || role === 'after_sales';
  return {
    id: row.id,
    username: row.username,
    role,
    firstName: row.firstname ?? null,
    lastName: row.lastname ?? null,
    canAdmin,
    canEditCrm,
  };
}

router.get('/status', (req, res) => {
  const count = db.prepare('SELECT COUNT(*) AS c FROM users').get().c;
  const needsBootstrap = count === 0;
  if (needsBootstrap) {
    return res.json({ needsBootstrap: true, loggedIn: false, user: null });
  }
  if (!req.session?.userId) {
    return res.json({ needsBootstrap: false, loggedIn: false, user: null });
  }
  const u = db
    .prepare(
      'SELECT id, username, firstname, lastname, role, active FROM users WHERE id = ?',
    )
    .get(req.session.userId);
  if (!u || !u.active) {
    req.session.destroy(() => {});
    return res.json({ needsBootstrap: false, loggedIn: false, user: null });
  }
  res.json({
    needsBootstrap: false,
    loggedIn: true,
    user: userPayload(u),
  });
});

router.post('/bootstrap', async (req, res) => {
  const count = db.prepare('SELECT COUNT(*) AS c FROM users').get().c;
  if (count > 0) {
    return res.status(403).json({ message: 'Initialisierung nicht mehr möglich.' });
  }
  const { username, password } = req.body || {};
  const un = String(username || '')
    .trim()
    .toLowerCase();
  if (!un || !password || password.length < 8) {
    return badRequest(res, 'Benutzername und Passwort (min. 8 Zeichen) erforderlich.');
  }
  const id = randomUUID();
  const ph = await hashPassword(password);
  db.prepare(
    `INSERT INTO users (id, username, password_hash, role, source, active, updated_at)
     VALUES (?, ?, ?, 'admin', 'local', 1, datetime('now'))`,
  ).run(id, un, ph);
  req.session.userId = id;
  req.session.role = 'admin';
  req.session.username = un;
  res.status(201).json({
    user: userPayload(
      db.prepare(
        'SELECT id, username, firstname, lastname, role FROM users WHERE id = ?',
      ).get(id),
    ),
  });
});

router.post('/login', async (req, res) => {
  const { username, password } = req.body || {};
  const rawUsername = String(username || '').trim();
  const unLower = rawUsername.toLowerCase();
  if (!rawUsername || !password) {
    return badRequest(res, 'Benutzername und Passwort erforderlich.');
  }

  const ldapCfg = loadIntegrations().ldap || {};
  const useLdap =
    Boolean(ldapCfg.syncEnabled) &&
    String(ldapCfg.serverUrl || '').trim() !== '' &&
    String(ldapCfg.searchBase || '').trim() !== '';

  if (useLdap) {
    const ar = await authenticateLdap(rawUsername, password, loadIntegrations);
    if (ar.ok) {
      const lookup = ar.canonicalUsername || rawUsername;
      const u = db
        .prepare('SELECT * FROM users WHERE username = ? COLLATE NOCASE')
        .get(lookup);
      if (!u || !u.active) {
        return res.status(401).json({
          message:
            'Benutzer nach LDAP nicht in der Anwendung gefunden. Bitte zuerst eine LDAP-Synchronisation ausführen.',
        });
      }
      req.session.userId = u.id;
      req.session.role = u.role;
      req.session.username = u.username;
      return res.json({
        user: userPayload(u),
      });
    }
    if (!ar.skipLdap) {
      const u = db
        .prepare('SELECT * FROM users WHERE username = ? COLLATE NOCASE')
        .get(unLower);
      if (u && u.active && u.password_hash) {
        const pwOk = await verifyPassword(password, u.password_hash);
        if (pwOk) {
          req.session.userId = u.id;
          req.session.role = u.role;
          req.session.username = u.username;
          return res.json({
            user: userPayload(u),
          });
        }
      }
      return res.status(401).json({ message: 'Ungültige Zugangsdaten.' });
    }
  }

  const u = db.prepare('SELECT * FROM users WHERE username = ?').get(unLower);
  if (!u || !u.active) {
    return res.status(401).json({ message: 'Ungültige Zugangsdaten.' });
  }
  if (!u.password_hash) {
    return res.status(401).json({
      message:
        'Kein lokales Passwort. LDAP ist nicht konfiguriert oder die Anmeldung ist nur mit Verzeichnis möglich.',
    });
  }
  const ok = await verifyPassword(password, u.password_hash);
  if (!ok) return res.status(401).json({ message: 'Ungültige Zugangsdaten.' });
  req.session.userId = u.id;
  req.session.role = u.role;
  req.session.username = u.username;
  res.json({
    user: userPayload(u),
  });
});

router.post('/logout', (req, res) => {
  req.session.destroy((err) => {
    if (err) return res.status(500).json({ message: 'Abmelden fehlgeschlagen.' });
    res.json({ ok: true });
  });
});

export default router;
