import { Router } from 'express';
import { clearSessionCookie, currentSession, login, logout, setSessionCookie } from '../auth.js';
import { createAuditEvent } from '../store.js';

export const authRouter = Router();

const loginAttempts = new Map();
const maxAttempts = 5;
const windowMs = 15 * 60 * 1000;

authRouter.get('/session', (req, res) => {
  const session = currentSession(req);
  res.json({ authenticated: Boolean(session), user: session?.user || null });
});

authRouter.post('/login', (req, res) => {
  const username = String(req.body?.username || '');
  const key = loginAttemptKey(req, username);
  const attempt = currentAttempt(key);
  if (attempt.count >= maxAttempts) {
    createAuditEvent({
      action: 'login_blocked',
      targetType: 'session',
      targetId: username || null,
      details: { ip: clientIp(req), reason: 'rate_limit' },
    });
    res.status(429).json({ error: 'Too many login attempts. Try again later.' });
    return;
  }

  const result = login(username, req.body?.password);
  if (!result) {
    recordFailedAttempt(key);
    createAuditEvent({
      action: 'login_failed',
      targetType: 'session',
      targetId: username || null,
      details: { ip: clientIp(req) },
    });
    res.status(401).json({ error: 'Invalid username or password.' });
    return;
  }
  loginAttempts.delete(key);
  setSessionCookie(res, result.session);
  createAuditEvent({
    user: result.user,
    action: 'login',
    targetType: 'session',
    targetId: result.session.id,
  });
  res.json({ user: result.user });
});

authRouter.post('/logout', (req, res) => {
  const session = currentSession(req);
  if (session) {
    createAuditEvent({
      user: session.user,
      action: 'logout',
      targetType: 'session',
      targetId: session.sessionId,
    });
  }
  logout(session?.sessionId);
  clearSessionCookie(res);
  res.json({ ok: true });
});

function loginAttemptKey(req, username) {
  return `${clientIp(req)}:${String(username || '').toLowerCase()}`;
}

function clientIp(req) {
  return String(req.ip || req.socket?.remoteAddress || '').replace(/^::ffff:/, '');
}

function currentAttempt(key) {
  const now = Date.now();
  const current = loginAttempts.get(key);
  if (!current || current.resetAt <= now) return { count: 0, resetAt: now + windowMs };
  return current;
}

function recordFailedAttempt(key) {
  const attempt = currentAttempt(key);
  loginAttempts.set(key, { count: attempt.count + 1, resetAt: attempt.resetAt });
}
