import { Response, NextFunction } from 'express';
import jwt, { SignOptions } from 'jsonwebtoken';
import { env } from '../config/env';
import { AuthRequest, JwtPayload } from '../shared/types';
import { respond } from '../shared/utils/apiResponse';

const VALID_API_KEYS = new Set(env.API_KEYS.split(',').map(k => k.trim()).filter(Boolean));

export function authenticate(req: AuthRequest, res: Response, next: NextFunction): void {
  const apiKey = req.headers['x-api-key'] as string | undefined;
  if (apiKey) {
    if (!VALID_API_KEYS.has(apiKey)) {
      respond.unauthorized(res, 'API Key inválida');
      return;
    }
    req.user = { sub: `apikey:${apiKey.slice(0, 8)}`, role: 'external', type: 'apikey' };
    next();
    return;
  }

  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    respond.unauthorized(res, 'Se requiere token de autenticación');
    return;
  }

  const token = authHeader.split(' ')[1];
  try {
    const payload = jwt.verify(token, env.JWT_SECRET) as JwtPayload;
    req.user = { ...payload, type: 'jwt' };
    next();
  } catch (err) {
    if (err instanceof jwt.TokenExpiredError) respond.unauthorized(res, 'El token ha expirado');
    else respond.unauthorized(res, 'Token inválido');
  }
}

export function generateToken(payload: Omit<JwtPayload, 'iat' | 'exp'>): string {
  const options: SignOptions = { expiresIn: env.JWT_EXPIRES_IN as SignOptions['expiresIn'] };
  return jwt.sign(payload, env.JWT_SECRET, options);
}
