'use strict';
const express = require('express');
const bcrypt  = require('bcryptjs');
const { getAllUsers, getUserById, createUser, updateUser } = require('./db');
const { requireRole } = require('./middleware');
const { getUsage: getSyncroUsage, getHistory: getSyncroHistory, getLimitHits: getSyncroLimitHits } = require('../syncroStats');

const router = express.Router();

const VALID_ROLES    = ['superduperadmin', 'admin', 'tech', 'client'];
const ELEVATED_ROLES = ['superduperadmin', 'admin'];

// GET /admin/users
router.get('/users', (req, res) => {
  res.json({ users: getAllUsers() });
});

// POST /admin/users — create user
router.post('/users', async (req, res) => {
  const username           = String(req.body?.username            ?? '').trim().toLowerCase();
  const name               = String(req.body?.name                ?? '').trim();
  const company            = String(req.body?.company             ?? '').trim();
  const syncroCustomerId   = req.body?.syncro_customer_id != null ? parseInt(req.body.syncro_customer_id, 10) : null;
  const role               = String(req.body?.role                ?? '');
  const password           = String(req.body?.password            ?? '');

  if (!username || !name || !role || !password) {
    return res.status(400).json({ error: 'All fields are required.' });
  }
  if (!VALID_ROLES.includes(role)) {
    return res.status(400).json({ error: 'Invalid role.' });
  }
  if (ELEVATED_ROLES.includes(role) && req.session.user.role !== 'superduperadmin') {
    return res.status(403).json({ error: 'Only superduperadmin can assign admin-level roles.' });
  }
  if (password.length < 12) {
    return res.status(400).json({ error: 'Password must be at least 12 characters.' });
  }

  const hash = await bcrypt.hash(password, 12);
  try {
    createUser(username, hash, name, role, company, syncroCustomerId);
    res.json({ ok: true });
  } catch (err) {
    if (err.message?.includes('UNIQUE constraint')) {
      return res.status(409).json({ error: 'Username already exists.' });
    }
    throw err;
  }
});

// PATCH /admin/users/:id — update user fields
router.patch('/users/:id', async (req, res) => {
  const id = parseInt(req.params.id, 10);
  if (isNaN(id)) return res.status(400).json({ error: 'Invalid user ID.' });

  const current = getUserById(id);
  if (!current) return res.status(404).json({ error: 'User not found.' });

  const isSelf = id === req.session.user.id;

  // Nobody can change their own active status or role via the API
  if (isSelf && 'active' in req.body) {
    return res.status(403).json({ error: 'Cannot change your own active status.' });
  }

  const fields = {};
  const { name, company, syncro_customer_id, role, active, password } = req.body ?? {};

  if (name !== undefined) {
    fields.name = String(name).trim();
    if (!fields.name) return res.status(400).json({ error: 'Name cannot be empty.' });
  }

  if (company !== undefined) {
    fields.company = String(company).trim();
  }

  if (syncro_customer_id !== undefined) {
    fields.syncro_customer_id = syncro_customer_id != null ? parseInt(syncro_customer_id, 10) : null;
  }

  if (role !== undefined && !isSelf) {
    if (!VALID_ROLES.includes(role)) return res.status(400).json({ error: 'Invalid role.' });
    if (ELEVATED_ROLES.includes(role) && req.session.user.role !== 'superduperadmin') {
      return res.status(403).json({ error: 'Only superduperadmin can assign admin-level roles.' });
    }
    fields.role = role;
  }

  if (active !== undefined) {
    fields.active = active ? 1 : 0;
  }

  if (password !== undefined && password !== '') {
    if (String(password).length < 12) {
      return res.status(400).json({ error: 'Password must be at least 12 characters.' });
    }
    fields.password_hash = await bcrypt.hash(String(password), 12);
  }

  updateUser(id, fields);
  res.json({ ok: true });
});

// GET /admin/syncro-usage — rolling 60s Syncro API request count + 7-day limit-hit count
router.get('/syncro-usage', (req, res) => {
  const limit = 180;
  res.json({ requests: getSyncroUsage(), limit, windowMs: 60_000, limitHits7d: getSyncroLimitHits(limit) });
});

// GET /admin/syncro-history?window=<ms> — per-minute buckets for the given window (max 7 days)
router.get('/syncro-history', (req, res) => {
  const raw      = parseInt(req.query.window ?? '3600000', 10);
  const windowMs = isNaN(raw) ? 3_600_000 : Math.min(Math.max(raw, 60_000), 7 * 24 * 60 * 60 * 1000);
  res.json({ buckets: getSyncroHistory(windowMs), windowMs });
});

// POST /admin/restart — exit cleanly; PM2 will restart the process
router.post('/restart', requireRole('superduperadmin'), (req, res) => {
  res.json({ ok: true });
  setTimeout(() => process.exit(0), 150);
});

module.exports = router;
