/**
 * Admin authentication middleware
 * Supports: (1) JWT via Authorization Bearer (when ADMIN_JWT_SECRET or JWT_SECRET set),
 *           (2) x-admin-token session (backward compatible)
 */

import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';

const JWT_SECRET = process.env.ADMIN_JWT_SECRET || process.env.JWT_SECRET;

// Simple in-memory session store (replace with Redis in production)
const sessions = new Map<string, { username: string; expires: number }>();

export interface AuthRequest extends Request {
  adminUser?: string;
}

export function requireAdmin(req: AuthRequest, res: Response, next: NextFunction): void {
  const bearer = req.headers.authorization;
  if (bearer?.startsWith('Bearer ') && JWT_SECRET) {
    const token = bearer.slice(7);
    try {
      const decoded = jwt.verify(token, JWT_SECRET) as { sub?: string; username?: string };
      req.adminUser = decoded.sub ?? decoded.username ?? 'unknown';
      return next();
    } catch {
      res.status(401).json({ error: 'Invalid or expired JWT' });
      return;
    }
  }

  const token = req.headers['x-admin-token'] as string;
  if (!token) {
    res.status(401).json({ error: 'Admin token or Bearer JWT required' });
    return;
  }

  const session = sessions.get(token);
  if (!session || session.expires < Date.now()) {
    sessions.delete(token);
    res.status(401).json({ error: 'Invalid or expired token' });
    return;
  }

  req.adminUser = session.username;
  next();
}

export function createSession(username: string): string {
  if (JWT_SECRET) {
    return jwt.sign(
      { sub: username, iat: Math.floor(Date.now() / 1000) },
      JWT_SECRET,
      { expiresIn: '24h' }
    );
  }
  const token = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
  sessions.set(token, {
    username,
    expires: Date.now() + 24 * 60 * 60 * 1000 // 24 hours
  });
  return token;
}

export function getClientIp(req: Request): string {
  return (req.headers['x-forwarded-for'] as string)?.split(',')[0] || 
         (req.headers['x-real-ip'] as string) || 
         req.socket.remoteAddress || 
         'unknown';
}

