const nodemailer = require('nodemailer');
const { all, audit, now, run } = require('../db');
const { logEvent } = require('../logger');

function readSettings() {
  const rows = all('SELECT key, value FROM app_settings');
  return Object.fromEntries(rows.map((row) => [row.key, row.value]));
}

// Raw config (includes password) — for sending mail only.
function getConfig() {
  const s = readSettings();
  return {
    host: s.smtp_host || '',
    port: Number(s.smtp_port || 587),
    secure: s.smtp_secure === 'true',
    user: s.smtp_user || '',
    password: s.smtp_password || '',
    from: s.smtp_from || s.smtp_user || '',
    enabled: s.alerts_enabled === 'true',
    leadDays: Number(s.alerts_lead_days || 30),
    recipients: String(s.alerts_recipients || '').split(',').map((x) => x.trim()).filter(Boolean),
    webhookEnabled: s.webhook_enabled === 'true',
    webhookUrl: s.webhook_url || '',
    webhookSecret: s.webhook_secret || ''
  };
}

// Safe config for the API/UI — password is never returned, only whether it is set.
function publicConfig() {
  const c = getConfig();
  return {
    smtp_host: c.host,
    smtp_port: c.port,
    smtp_secure: c.secure,
    smtp_user: c.user,
    smtp_from: c.from,
    smtp_password_set: Boolean(c.password),
    alerts_enabled: c.enabled,
    alerts_lead_days: c.leadDays,
    alerts_recipients: c.recipients.join(', '),
    configured: Boolean(c.host),
    webhook_enabled: c.webhookEnabled,
    webhook_url: c.webhookUrl,
    webhook_secret_set: Boolean(c.webhookSecret),
    webhook_configured: Boolean(c.webhookUrl)
  };
}

function setValue(key, value) {
  run(
    'INSERT INTO app_settings (key, value, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at',
    [key, String(value), now()]
  );
}

function saveConfig(body, userId) {
  if (body.smtp_host !== undefined) setValue('smtp_host', body.smtp_host || '');
  if (body.smtp_port !== undefined) setValue('smtp_port', Number(body.smtp_port) || 587);
  if (body.smtp_secure !== undefined) setValue('smtp_secure', body.smtp_secure ? 'true' : 'false');
  if (body.smtp_user !== undefined) setValue('smtp_user', body.smtp_user || '');
  if (body.smtp_from !== undefined) setValue('smtp_from', body.smtp_from || '');
  if (body.smtp_password) setValue('smtp_password', body.smtp_password); // only overwrite when a new value is supplied
  if (body.alerts_enabled !== undefined) setValue('alerts_enabled', body.alerts_enabled ? 'true' : 'false');
  if (body.alerts_lead_days !== undefined) setValue('alerts_lead_days', Number(body.alerts_lead_days) || 30);
  if (body.alerts_recipients !== undefined) setValue('alerts_recipients', body.alerts_recipients || '');
  if (body.webhook_enabled !== undefined) setValue('webhook_enabled', body.webhook_enabled ? 'true' : 'false');
  if (body.webhook_url !== undefined) setValue('webhook_url', body.webhook_url || '');
  if (body.webhook_secret_clear) setValue('webhook_secret', '');
  else if (body.webhook_secret) setValue('webhook_secret', body.webhook_secret); // only overwrite when a new value is supplied
  audit(userId, 'update', 'notification_settings', 'smtp', null, {
    ...body,
    smtp_password: body.smtp_password ? '[set]' : undefined,
    webhook_secret: body.webhook_secret ? '[set]' : undefined
  });
  return publicConfig();
}

function getTransport() {
  const c = getConfig();
  if (!c.host) {
    throw Object.assign(new Error('SMTP host is not configured'), { status: 400 });
  }
  return nodemailer.createTransport({
    host: c.host,
    port: c.port,
    secure: c.secure,
    auth: c.user ? { user: c.user, pass: c.password } : undefined
  });
}

async function sendMail({ to, subject, html, text }) {
  const c = getConfig();
  const recipients = to ? (Array.isArray(to) ? to : [to]) : c.recipients;
  if (!recipients.length) {
    throw Object.assign(new Error('No recipients are configured'), { status: 400 });
  }
  const transport = getTransport();
  try {
    const info = await transport.sendMail({
      from: c.from || c.user,
      to: recipients.join(', '),
      subject,
      html,
      text
    });
    logEvent('smtp', `Email sent: "${subject}" to ${recipients.length} recipient(s)`, { subject, recipients: recipients.length, host: c.host, messageId: info.messageId });
    return info;
  } catch (error) {
    logEvent('smtp', `Email send failed: "${subject}" — ${error.message}`, { subject, recipients: recipients.length, host: c.host }, 'error');
    throw error;
  }
}

async function sendTestEmail(to, userId) {
  const info = await sendMail({
    to: to ? [to] : null,
    subject: 'DepreCore test email',
    html: '<p>Your DepreCore SMTP settings are working. This is a test message.</p>',
    text: 'Your DepreCore SMTP settings are working. This is a test message.'
  });
  audit(userId, 'send', 'test_email', null, null, { to });
  return { messageId: info.messageId, accepted: info.accepted };
}

module.exports = { getConfig, publicConfig, saveConfig, sendMail, sendTestEmail };
