// @ts-nocheck — route controller converted to .cts; handler req/res typed, full type-check deferred (thin glue over typed services).
import type { Req, Res, Next } from '../types/http';
const express = require('express');
const router = express.Router();
const { getDb, getSetting, setSetting } = require('../db/database.cts');
const { requireAuth, requireUser, requireAdmin } = require('../middleware/requireAuth.cts');
const { sendTestEmail } = require('../services/notificationService.cts');
const { sendTestPush } = require('../services/notificationService.cts')._push || {};
const { decryptSecret } = require('../services/encryptionService.cts');
const { encryptSecret } = require('../services/encryptionService.cts');

// ── Admin: SMTP configuration ─────────────────────────────────────────────────

// GET /api/notifications/admin — read all SMTP settings (password masked)
router.get('/admin', requireAuth, requireAdmin, (req: Req, res: Res) => {
  const keys = [
    'notify_smtp_enabled',
    'notify_sender_name',
    'notify_sender_address',
    'notify_smtp_host',
    'notify_smtp_port',
    'notify_smtp_encryption',
    'notify_smtp_self_signed',
    'notify_smtp_username',
    'notify_smtp_password',
    'notify_allow_user_config',
    'notify_global_recipient',
    'reminder_hour',
  ];
  const settings = {};
  for (const k of keys) settings[k] = getSetting(k) || '';
  if (!settings.reminder_hour) settings.reminder_hour = '6';
  // Mask password in response
  if (settings.notify_smtp_password) settings.notify_smtp_password = '••••••••';
  res.json(settings);
});

// PUT /api/notifications/admin — save SMTP settings
router.put('/admin', requireAuth, requireAdmin, (req: Req, res: Res) => {
  const allowed = [
    'notify_smtp_enabled',
    'notify_sender_name',
    'notify_sender_address',
    'notify_smtp_host',
    'notify_smtp_port',
    'notify_smtp_encryption',
    'notify_smtp_self_signed',
    'notify_smtp_username',
    'notify_allow_user_config',
    'notify_global_recipient',
  ];
  for (const key of allowed) {
    if (req.body[key] !== undefined) setSetting(key, req.body[key]);
  }
  // Only update password if a real value was sent (not the masked placeholder)
  if (req.body.notify_smtp_password && !req.body.notify_smtp_password.startsWith('•')) {
    setSetting('notify_smtp_password', encryptSecret(req.body.notify_smtp_password));
  }
  // Reminder send-hour (0–23, global): persist clamped + live-reschedule the cron.
  if (req.body.reminder_hour !== undefined) {
    const h = parseInt(req.body.reminder_hour, 10);
    const hour = Number.isInteger(h) && h >= 0 && h <= 23 ? h : 6;
    setSetting('reminder_hour', String(hour));
    try {
      require('../workers/dailyWorker.cts').rescheduleDailyWorker();
    } catch (err) {
      console.error('[notifications] Failed to reschedule daily worker:', err.message);
    }
  }
  res.json({ success: true });
});

// POST /api/notifications/test — send a test email
router.post('/test', requireAuth, requireAdmin, async (req: Req, res: Res) => {
  const { to } = req.body;
  if (!to) return res.status(400).json({ error: 'Recipient address required' });
  try {
    await sendTestEmail(to);
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ── User: notification preferences ───────────────────────────────────────────

// GET /api/notifications/me — user prefs + whether admin has enabled it
router.get('/me', requireAuth, requireUser, (req: Req, res: Res) => {
  const db = getDb();
  const user = db
    .prepare(
      `
    SELECT notification_email, notifications_enabled,
           notify_3d, notify_1d, notify_due, notify_overdue, notify_amount_change
    FROM users WHERE id = ?
  `,
    )
    .get(req.user.id);

  res.json({
    smtp_enabled: getSetting('notify_smtp_enabled') === 'true',
    allow_user_config: getSetting('notify_allow_user_config') === 'true',
    notification_email: user.notification_email || '',
    notifications_enabled: !!user.notifications_enabled,
    notify_3d: !!user.notify_3d,
    notify_1d: !!user.notify_1d,
    notify_due: !!user.notify_due,
    notify_overdue: !!user.notify_overdue,
    notify_amount_change: user.notify_amount_change !== 0,
  });
});

// PUT /api/notifications/me — save user prefs
router.put('/me', requireAuth, requireUser, (req: Req, res: Res) => {
  const db = getDb();
  const {
    notification_email,
    notifications_enabled,
    notify_3d,
    notify_1d,
    notify_due,
    notify_overdue,
    notify_amount_change,
  } = req.body;

  db.prepare(
    `
    UPDATE users SET
      notification_email    = ?,
      notifications_enabled = ?,
      notify_3d             = ?,
      notify_1d             = ?,
      notify_due            = ?,
      notify_overdue        = ?,
      notify_amount_change  = ?,
      updated_at            = datetime('now')
    WHERE id = ?
  `,
  ).run(
    notification_email || null,
    notifications_enabled ? 1 : 0,
    notify_3d !== false ? 1 : 0,
    notify_1d !== false ? 1 : 0,
    notify_due !== false ? 1 : 0,
    notify_overdue !== false ? 1 : 0,
    notify_amount_change !== false ? 1 : 0,
    req.user.id,
  );

  res.json({ success: true });
});

// POST /api/notifications/test-push — send a test push notification to the current user
router.post('/test-push', requireAuth, requireUser, async (req: Req, res: Res) => {
  const db = getDb();
  const user = db
    .prepare(
      `
    SELECT notify_push_enabled, push_channel, push_url, push_token, push_chat_id
    FROM users WHERE id = ?
  `,
    )
    .get(req.user.id);

  if (!user?.push_channel || !user?.push_url) {
    return res.status(400).json({ error: 'Push notification channel not configured' });
  }

  // Decrypt for sending
  const safeDecrypt = (v) => {
    try {
      return v ? decryptSecret(v) : '';
    } catch {
      return v || '';
    }
  };
  const userForPush = {
    ...user,
    notify_push_enabled: 1,
    push_url: safeDecrypt(user.push_url),
    push_token: safeDecrypt(user.push_token),
  };

  try {
    if (!sendTestPush) throw new Error('Push service not initialised');
    await sendTestPush(userForPush);
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

module.exports = router;
