import crypto from "crypto";
import nodemailer from "nodemailer";
import { pool } from "../config/db.js";
import { hashPassword, generateToken } from "../middleware/auth.js";
import { writeAuditLog } from "../utils/audit.js";

// ── Helpers ──────────────────────────────────────────────────────────────────

function generateResetToken() {
  return crypto.randomBytes(32).toString("hex");
}

/** Read SMTP config: prefer DB settings, fall back to .env */
async function getSmtpConfig() {
  try {
    const [rows] = await pool.query(
      "SELECT clave, valor FROM configuracion WHERE clave IN ('smtp_host','smtp_port','smtp_user','smtp_pass','smtp_from')"
    );
    const cfg = {};
    for (const r of rows) cfg[r.clave] = r.valor;

    return {
      host:  cfg.smtp_host  || process.env.SMTP_HOST  || "smtp.mailtrap.io",
      port:  Number(cfg.smtp_port  || process.env.SMTP_PORT  || 2525),
      user:  cfg.smtp_user  || process.env.SMTP_USER  || "",
      pass:  cfg.smtp_pass  || process.env.SMTP_PASS  || "",
      from:  cfg.smtp_from  || process.env.SMTP_FROM  || "noreply@laundryapp.com",
    };
  } catch {
    return {
      host: process.env.SMTP_HOST || "smtp.mailtrap.io",
      port: Number(process.env.SMTP_PORT || 2525),
      user: process.env.SMTP_USER || "",
      pass: process.env.SMTP_PASS || "",
      from: process.env.SMTP_FROM || "noreply@laundryapp.com",
    };
  }
}

function createTransporter(cfg) {
  return nodemailer.createTransport({
    host:   cfg.host,
    port:   cfg.port,
    secure: cfg.port === 465,
    auth:   (cfg.user && cfg.pass) ? { user: cfg.user, pass: cfg.pass } : undefined,
    tls:    { rejectUnauthorized: false }
  });
}

function resetEmailHtml(resetToken, frontendUrl) {
  const resetUrl = `${frontendUrl}/#reset?token=${resetToken}`;
  return `
<!DOCTYPE html>
<html lang="es">
<head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/></head>
<body style="margin:0;padding:0;font-family:Inter,'Segoe UI',Arial,sans-serif;background:#F4FCFF;">
  <table width="100%" cellpadding="0" cellspacing="0" style="padding:40px 20px;">
    <tr><td align="center">
      <table width="560" cellpadding="0" cellspacing="0" style="background:#ffffff;border-radius:24px;overflow:hidden;box-shadow:0 20px 60px rgba(8,119,255,.12);border:1px solid #D9E3F0;">
        <tr>
          <td style="background:linear-gradient(135deg,#0877FF,#25C7D9);padding:36px 40px;text-align:center;">
            <div style="background:rgba(255,255,255,.2);border-radius:16px;display:inline-block;padding:14px 18px;margin-bottom:18px;"><span style="font-size:32px;">🧺</span></div>
            <h1 style="margin:0;color:#fff;font-size:26px;font-weight:900;letter-spacing:-0.5px;">Laundry App</h1>
            <p style="margin:8px 0 0;color:rgba(255,255,255,.85);font-size:14px;">Restablecimiento de Contraseña</p>
          </td>
        </tr>
        <tr>
          <td style="padding:40px;">
            <p style="margin:0 0 10px;font-size:16px;color:#0B1B3F;font-weight:700;">Hola,</p>
            <p style="margin:0 0 28px;font-size:15px;color:#5B6680;line-height:1.6;">
              Recibimos una solicitud para restablecer la contraseña de tu cuenta. 
              Usa el código de verificación de abajo o haz clic en el botón para continuar.
            </p>
            <div style="background:linear-gradient(135deg,#F4FCFF,#E7F4FF);border:1.5px solid #D9E3F0;border-radius:16px;padding:24px;text-align:center;margin:0 0 28px;">
              <p style="margin:0 0 8px;font-size:12px;color:#7B879D;font-weight:800;text-transform:uppercase;letter-spacing:.08em;">Tu código de restablecimiento</p>
              <div style="font-family:'Courier New',monospace;font-size:13px;font-weight:900;color:#0877FF;background:#fff;border:1.5px solid #D9E3F0;border-radius:10px;padding:12px 18px;word-break:break-all;letter-spacing:1px;">${resetToken}</div>
              <p style="margin:10px 0 0;font-size:12px;color:#7B879D;">Este código expira en <strong>30 minutos</strong></p>
            </div>
            <div style="text-align:center;margin:0 0 32px;">
              <a href="${resetUrl}" style="display:inline-block;background:linear-gradient(135deg,#0877FF,#005ED6);color:#fff;text-decoration:none;border-radius:14px;padding:16px 36px;font-size:15px;font-weight:800;box-shadow:0 12px 28px rgba(8,119,255,.28);">
                🔑 Restablecer Contraseña
              </a>
            </div>
            <div style="background:#FFF7E6;border:1px solid #FFD580;border-radius:12px;padding:16px;margin:0 0 24px;">
              <p style="margin:0;font-size:13px;color:#92400E;line-height:1.5;">
                ⚠️ <strong>Si no solicitaste este cambio</strong>, ignora este correo. Tu contraseña permanecerá sin cambios.
              </p>
            </div>
            <p style="margin:0;font-size:13px;color:#7B879D;line-height:1.5;">
              Si el botón no funciona, copia y pega este enlace en tu navegador:<br/>
              <a href="${resetUrl}" style="color:#0877FF;word-break:break-all;font-size:12px;">${resetUrl}</a>
            </p>
          </td>
        </tr>
        <tr>
          <td style="background:#F4FCFF;padding:20px 40px;border-top:1px solid #D9E3F0;text-align:center;">
            <p style="margin:0;font-size:12px;color:#7B879D;">© ${new Date().getFullYear()} Laundry App · Panel Administrativo</p>
          </td>
        </tr>
      </table>
    </td></tr>
  </table>
</body>
</html>`;
}

function testEmailHtml(toEmail) {
  return `
<!DOCTYPE html>
<html lang="es">
<head><meta charset="UTF-8"/></head>
<body style="margin:0;padding:0;font-family:Inter,'Segoe UI',Arial,sans-serif;background:#F4FCFF;">
  <table width="100%" cellpadding="0" cellspacing="0" style="padding:40px 20px;">
    <tr><td align="center">
      <table width="520" cellpadding="0" cellspacing="0" style="background:#fff;border-radius:20px;overflow:hidden;box-shadow:0 16px 48px rgba(8,119,255,.10);border:1px solid #D9E3F0;">
        <tr>
          <td style="background:linear-gradient(135deg,#059669,#34D399);padding:30px 36px;text-align:center;">
            <div style="font-size:42px;margin-bottom:12px;">✅</div>
            <h1 style="margin:0;color:#fff;font-size:22px;font-weight:900;">¡SMTP Configurado Correctamente!</h1>
          </td>
        </tr>
        <tr>
          <td style="padding:36px;">
            <p style="font-size:15px;color:#0B1B3F;line-height:1.6;margin:0 0 20px;">
              Este es un <strong>email de prueba</strong> generado desde el panel de configuración de <strong>Laundry App</strong>.
            </p>
            <div style="background:#EAF8F0;border:1px solid rgba(46,154,98,.25);border-radius:12px;padding:18px;margin-bottom:20px;">
              <table width="100%" cellpadding="0" cellspacing="0">
                <tr><td style="font-size:13px;color:#2E9A62;font-weight:800;padding-bottom:8px;">📧 Detalles del envío</td></tr>
                <tr><td style="font-size:13px;color:#5B6680;padding:4px 0;">Destinatario: <strong>${toEmail}</strong></td></tr>
                <tr><td style="font-size:13px;color:#5B6680;padding:4px 0;">Fecha: ${new Date().toLocaleString("es-DO")}</td></tr>
                <tr><td style="font-size:13px;color:#5B6680;padding:4px 0;">Sistema: Laundry App v1.0</td></tr>
              </table>
            </div>
            <p style="font-size:13px;color:#7B879D;margin:0;">
              Si recibiste este correo, tu configuración SMTP funciona correctamente. 
              Los emails de restablecimiento de contraseña y notificaciones del sistema serán enviados desde esta cuenta.
            </p>
          </td>
        </tr>
        <tr>
          <td style="background:#F4FCFF;padding:16px 36px;border-top:1px solid #D9E3F0;text-align:center;">
            <p style="margin:0;font-size:12px;color:#7B879D;">© ${new Date().getFullYear()} Laundry App · Panel Administrativo</p>
          </td>
        </tr>
      </table>
    </td></tr>
  </table>
</body>
</html>`;
}

// ── Controllers ───────────────────────────────────────────────────────────────

export async function login(req, res, next) {
  try {
    const { username, password } = req.body;

    if (!username || !password) {
      return res.status(400).json({
        success: false,
        message: "El nombre de usuario y contraseña son requeridos"
      });
    }

    const [rows] = await pool.query(
      "SELECT id, username, password, role FROM users WHERE username = ?",
      [username.trim()]
    );

    if (!rows.length) {
      return res.status(401).json({ success: false, message: "Usuario o contraseña incorrectos" });
    }

    const user = rows[0];
    if (user.password !== hashPassword(password)) {
      return res.status(401).json({ success: false, message: "Usuario o contraseña incorrectos" });
    }

    res.json({
      success: true,
      message: "Inicio de sesión correcto",
      data: {
        id: user.id,
        username: user.username,
        role: user.role,
        token: (
          await writeAuditLog(
            { ...req, user: { id: user.id, username: user.username, role: user.role } },
            { action: "login", entity: "auth", entityId: user.id }
          ),
          generateToken(user)
        )
      }
    });
  } catch (err) {
    next(err);
  }
}

export async function forgotPassword(req, res, next) {
  try {
    const { email } = req.body;

    if (!email || !email.trim()) {
      return res.status(400).json({ success: false, message: "El correo electrónico es requerido" });
    }

    const [rows] = await pool.query(
      "SELECT id, username, email FROM users WHERE email = ? AND status = 'active'",
      [email.trim().toLowerCase()]
    );

    // Generic response to prevent user enumeration
    const genericOk = {
      success: true,
      message: "Si el correo está registrado, recibirás las instrucciones en breve."
    };

    if (!rows.length) return res.json(genericOk);

    const user = rows[0];
    const resetToken = generateResetToken();
    const expiresMinutes = Number(process.env.RESET_TOKEN_EXPIRES_MIN) || 30;
    const expiresAt = new Date(Date.now() + expiresMinutes * 60 * 1000);

    await pool.query(
      "UPDATE users SET reset_token = ?, reset_token_expires = ? WHERE id = ?",
      [resetToken, expiresAt, user.id]
    );

    const frontendUrl = process.env.FRONTEND_URL || "http://localhost:5176";
    const cfg = await getSmtpConfig();
    const transporter = createTransporter(cfg);

    let emailError = null;
    try {
      await transporter.sendMail({
        from: `"Laundry App" <${cfg.from}>`,
        to: user.email,
        subject: "🔑 Restablece tu contraseña — Laundry App",
        html: resetEmailHtml(resetToken, frontendUrl)
      });
    } catch (mailErr) {
      emailError = mailErr.message;
      console.error("❌ Email send error:", mailErr.message);
    }

    const response = { ...genericOk };

    // In development or if email failed, expose token for testing
    if (process.env.NODE_ENV !== "production" || emailError) {
      response.devToken = resetToken;
      if (emailError) {
        response.emailError = "SMTP no configurado — usa el token de abajo para continuar.";
      }
    }

    res.json(response);
  } catch (err) {
    next(err);
  }
}

export async function resetPassword(req, res, next) {
  try {
    const { token, newPassword } = req.body;

    if (!token || !newPassword) {
      return res.status(400).json({ success: false, message: "El token y la nueva contraseña son requeridos" });
    }

    if (newPassword.length < 6) {
      return res.status(400).json({ success: false, message: "La contraseña debe tener al menos 6 caracteres" });
    }

    const [rows] = await pool.query(
      "SELECT id, username FROM users WHERE reset_token = ? AND reset_token_expires > NOW()",
      [token.trim()]
    );

    if (!rows.length) {
      return res.status(400).json({
        success: false,
        message: "El token es inválido o ha expirado. Solicita un nuevo enlace."
      });
    }

    await pool.query(
      "UPDATE users SET password = ?, reset_token = NULL, reset_token_expires = NULL, updated_at = NOW() WHERE id = ?",
      [hashPassword(newPassword), rows[0].id]
    );

    res.json({ success: true, message: "Contraseña actualizada correctamente. Ya puedes iniciar sesión." });
  } catch (err) {
    next(err);
  }
}

export async function validateResetToken(req, res, next) {
  try {
    const { token } = req.params;
    if (!token) return res.status(400).json({ success: false, message: "Token requerido" });

    const [rows] = await pool.query(
      "SELECT id, username FROM users WHERE reset_token = ? AND reset_token_expires > NOW()",
      [token.trim()]
    );

    if (!rows.length) return res.json({ success: false, message: "Token inválido o expirado" });

    res.json({ success: true, username: rows[0].username });
  } catch (err) {
    next(err);
  }
}

export async function testEmail(req, res, next) {
  try {
    const { toEmail, smtpHost, smtpPort, smtpUser, smtpPass, smtpFrom } = req.body;

    if (!toEmail || !toEmail.trim()) {
      return res.status(400).json({ success: false, message: "El correo destinatario es requerido" });
    }

    // Use provided values (from the form) or fall back to DB / env
    let cfg;
    if (smtpHost) {
      cfg = {
        host: smtpHost,
        port: Number(smtpPort) || 587,
        user: smtpUser || "",
        pass: smtpPass || "",
        from: smtpFrom || process.env.SMTP_FROM || "noreply@laundryapp.com"
      };
    } else {
      cfg = await getSmtpConfig();
    }

    const transporter = createTransporter(cfg);

    // Verify connection first
    try {
      await transporter.verify();
    } catch (verifyErr) {
      return res.status(400).json({
        success: false,
        message: `Error de conexión SMTP: ${verifyErr.message}. Verifica host, puerto y credenciales.`
      });
    }

    await transporter.sendMail({
      from: `"Laundry App" <${cfg.from}>`,
      to: toEmail.trim(),
      subject: "✅ Email de Prueba — Laundry App",
      html: testEmailHtml(toEmail.trim())
    });

    res.json({
      success: true,
      message: `Email de prueba enviado correctamente a ${toEmail.trim()}.`,
      config: { host: cfg.host, port: cfg.port, from: cfg.from }
    });
  } catch (err) {
    next(err);
  }
}
