'use strict';

const express = require('express');
const router  = express.Router();
const bcrypt  = require('bcryptjs');

const { getDb, getSetting } = require('../db/database');
const { hashPassword }      = require('../services/authService');
const { getImportHistory }  = require('../services/spreadsheetImportService');
const { passwordLimiter }   = require('../middleware/rateLimiter');

// All profile routes require authentication — enforced in server.js.
// req.user is always the signed-in user; user_id is never accepted from the body.

// ── GET /api/profile ──────────────────────────────────────────────────────────
// Returns safe profile data for the signed-in user.
// Never returns password_hash, session tokens, or secrets.
router.get('/', (req, res) => {
  const db   = getDb();
  const user = db.prepare(`
    SELECT id, username, display_name, role,
           first_login, created_at, updated_at,
           last_password_change_at,
           notification_email, notifications_enabled,
           notify_3d, notify_1d, notify_due, notify_overdue
    FROM users WHERE id = ?
  `).get(req.user.id);

  if (!user) return res.status(404).json({ error: 'User not found' });

  res.json({
    id:                      user.id,
    username:                user.username,
    display_name:            user.display_name || null,
    role:                    user.role,
    created_at:              user.created_at,
    updated_at:              user.updated_at,
    last_password_change_at: user.last_password_change_at || null,
    first_login:             !!user.first_login,
    notifications: {
      email:          user.notification_email  || null,
      enabled:        !!user.notifications_enabled,
      notify_3d:      !!user.notify_3d,
      notify_1d:      !!user.notify_1d,
      notify_due:     !!user.notify_due,
      notify_overdue: !!user.notify_overdue,
    },
    exports: {
      user_db:    '/api/export/user-db',
      user_excel: '/api/export/user-excel',
    },
    import_history_url: '/api/profile/import-history',
  });
});

// ── PATCH /api/profile ────────────────────────────────────────────────────────
// Updates safe profile fields: display_name only.
// Ignores any unknown or restricted fields.
router.patch('/', (req, res) => {
  const { display_name } = req.body;

  if (display_name !== undefined) {
    if (typeof display_name !== 'string') {
      return res.status(400).json({ error: 'display_name must be a string' });
    }
    const trimmed = display_name.trim();
    if (trimmed.length > 100) {
      return res.status(400).json({ error: 'display_name must be 100 characters or fewer' });
    }

    getDb().prepare(
      "UPDATE users SET display_name = ?, updated_at = datetime('now') WHERE id = ?"
    ).run(trimmed || null, req.user.id);
  }

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

// ── GET /api/profile/settings ─────────────────────────────────────────────────
// Returns user-owned notification preferences from the users table.
// Does not return admin/global/SMTP settings.
router.get('/settings', (req, res) => {
  const db   = getDb();
  const user = db.prepare(`
    SELECT notification_email, notifications_enabled,
           notify_3d, notify_1d, notify_due, notify_overdue
    FROM users WHERE id = ?
  `).get(req.user.id);

  if (!user) return res.status(404).json({ error: 'User not found' });

  res.json({
    notification_email:    user.notification_email  || null,
    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,
  });
});

// ── PATCH /api/profile/settings ───────────────────────────────────────────────
// Updates user-owned notification preferences only.
// Cannot modify global/admin/SMTP settings through this endpoint.
router.patch('/settings', (req, res) => {
  const db = getDb();
  const {
    notification_email, notifications_enabled,
    notify_3d, notify_1d, notify_due, notify_overdue,
  } = req.body;

  if (notification_email !== undefined && notification_email !== null) {
    if (typeof notification_email !== 'string') {
      return res.status(400).json({ error: 'notification_email must be a string' });
    }
    if (notification_email.trim().length > 255) {
      return res.status(400).json({ error: 'notification_email is too long' });
    }
  }

  const current = db.prepare(`
    SELECT notification_email, notifications_enabled,
           notify_3d, notify_1d, notify_due, notify_overdue
    FROM users WHERE id = ?
  `).get(req.user.id);

  const emailVal = notification_email !== undefined
    ? (notification_email ? notification_email.trim() || null : null)
    : current.notification_email;

  const boolVal = (incoming, fallback) =>
    incoming !== undefined ? (incoming ? 1 : 0) : fallback;

  db.prepare(`
    UPDATE users SET
      notification_email    = ?,
      notifications_enabled = ?,
      notify_3d             = ?,
      notify_1d             = ?,
      notify_due            = ?,
      notify_overdue        = ?,
      updated_at            = datetime('now')
    WHERE id = ?
  `).run(
    emailVal,
    boolVal(notifications_enabled, current.notifications_enabled),
    boolVal(notify_3d,             current.notify_3d),
    boolVal(notify_1d,             current.notify_1d),
    boolVal(notify_due,            current.notify_due),
    boolVal(notify_overdue,        current.notify_overdue),
    req.user.id,
  );

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

// ── POST /api/profile/change-password ─────────────────────────────────────────
// Changes the signed-in user's password.
// Always requires: current_password, new_password, confirm_new_password.
// Never bypasses current_password verification regardless of must_change_password.
// Never accepts user_id from the request body.
router.post('/change-password', passwordLimiter, async (req, res) => {
  const { current_password, new_password, confirm_new_password } = req.body;

  if (!current_password) {
    return res.status(400).json({ error: 'current_password is required' });
  }
  if (!new_password) {
    return res.status(400).json({ error: 'new_password is required' });
  }
  if (!confirm_new_password) {
    return res.status(400).json({ error: 'confirm_new_password is required' });
  }
  if (new_password !== confirm_new_password) {
    return res.status(400).json({ error: 'new passwords do not match' });
  }
  if (new_password.length < 8) {
    return res.status(400).json({ error: 'new password must be at least 8 characters' });
  }

  const db   = getDb();
  const user = db.prepare('SELECT password_hash FROM users WHERE id = ?').get(req.user.id);
  if (!user) return res.status(404).json({ error: 'User not found' });

  const valid = await bcrypt.compare(current_password, user.password_hash);
  if (!valid) {
    return res.status(401).json({ error: 'current password is incorrect' });
  }

  const hash = await hashPassword(new_password);

  db.prepare(`
    UPDATE users
    SET password_hash = ?, must_change_password = 0,
        last_password_change_at = datetime('now'),
        updated_at = datetime('now')
    WHERE id = ?
  `).run(hash, req.user.id);

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

// ── GET /api/profile/exports ──────────────────────────────────────────────────
// Returns metadata about available user export capabilities.
// Does not trigger any download; links point to the actual export endpoints.
router.get('/exports', (req, res) => {
  res.json({
    exports: [
      {
        id:          'user_db',
        label:       'SQLite database export',
        description: "Your bills, categories, payments, and notes as a portable SQLite file",
        url:         '/api/export/user-db',
        method:      'GET',
      },
      {
        id:          'user_excel',
        label:       'Excel databook export',
        description: "Your data as an Excel workbook with multiple sheets",
        url:         '/api/export/user-excel',
        method:      'GET',
      },
    ],
  });
});

// ── GET /api/profile/import-history ──────────────────────────────────────────
// Returns the signed-in user's import history.
// Delegates to the same service as GET /api/import/history.
router.get('/import-history', (req, res) => {
  try {
    const history = getImportHistory(req.user.id);
    res.json({ history });
  } catch (err) {
    console.error('[profile] import-history error:', err.message);
    res.status(500).json({ error: 'Failed to load import history' });
  }
});

module.exports = router;
