const server_constants = require('../tools/server_constants');

var { User } = require('../models/user');

const tools = require('../tools/general');

const auth_default = (req, res, next) => {
  if (req.body.keyappid === process.env.KEY_APP_ID) next();
};

const authenticateMiddleware = async (req, res, next, withUser = false, lean = false, noError = false) => {
  // Wrapper per res.send che logga automaticamente
  const originalSend = res.send;
  res.send = function (data) {
    logResponse(req, res, data);
    return originalSend.call(this, data);
  };

  try {
    const logPrefix = noError ? (withUser ? (lean ? 'WITHUSERLEAN' : 'WITHUSER') : 'NOERROR') : 'AUTH';

    
    // Validazione token
    const token = req.header('x-auth');
    const browser_random = req.header('x-browser-random');
    const refreshToken = req.header('x-refrtok');
    if (!token) {
      return handleAuthFailure(req, res, next, {
        code: server_constants.RIS_CODE_HTTP_INVALID_TOKEN,
        message: 'TOKEN INVALIDO',
        logPrefix,
        noError,
      });
    }

    // Recupera utente
    const user = await User.findByToken(token, 'auth', browser_random, false, withUser, lean);

    // Imposta dati richiesta
    req.user = user.code === server_constants.RIS_CODE_OK ? user.user : null;
    req.token = user.code === server_constants.RIS_CODE_OK ? token : null;
    req.refreshToken = refreshToken;
    req.browser_random = browser_random;
    req.code = user.code;
    req.statuscode2 = null;

    // Gestione token scaduto
    if (user.code === server_constants.RIS_CODE_HTTP_TOKEN_EXPIRED) {
      return handleAuthFailure(req, res, next, {
        code: server_constants.RIS_CODE_HTTP_TOKEN_EXPIRED,
        message: 'TOKEN SCADUTO',
        logPrefix,
        noError,
      });
    }

    // Gestione altri errori di autenticazione
    if (user.code !== server_constants.RIS_CODE_OK) {
      return handleAuthFailure(req, res, next, {
        code: user.code,
        message: 'AUTENTICAZIONE FALLITA',
        logPrefix,
        noError,
      });
    }

    next();
  } catch (e) {
    console.error('❌ Errore nel middleware di autenticazione:', e);
    return handleAuthFailure(req, res, next, {
      code: server_constants.RIS_CODE_HTTP_INVALID_TOKEN,
      message: 'ERRORE INTERNO',
      logPrefix: 'ERROR',
      noError,
    });
  }
};

// Funzione helper per gestire i fallimenti di autenticazione
function handleAuthFailure(req, res, next, { code, message, logPrefix, noError }) {
  req.user = null;
  req.token = null;
  req.code = code;

  if (noError) {
    req.statuscode2 = code;
    // console.log(`   ## ${logPrefix} - ${message} (noError mode, continuing) ⚠️`);
    return next();
  } else {
    console.log(`   ## SEND RES ${logPrefix} - ${message} ❌`);
    return res.status(code).send();
  }
}

// Funzione per loggare le risposte
function logResponse(req, res, data) {
  const statusCode = res.statusCode;
  const method = req.method;
  const url = req.originalUrl || req.url;
  const userId = req.user?._id || req.user?.id || 'N/A';

  const emoji = statusCode >= 200 && statusCode < 300 ? '✅' : statusCode >= 400 && statusCode < 500 ? '⚠️' : '❌';

  if (statusCode !== 200) {
    console.log(
      `${emoji} [${method}] ${url} | Status: ${statusCode} | User: ${userId} | Data: ${data ? JSON.stringify(data).substring(0, 100) : 'empty'
      }`
    );
  }
}

const authenticate = (req, res, next) => authenticateMiddleware(req, res, next);
const authenticate_withUser = (req, res, next) => authenticateMiddleware(req, res, next, true);
const authenticate_withUserLean = (req, res, next) => authenticateMiddleware(req, res, next, true, true);
const authenticate_noerror = (req, res, next) => authenticateMiddleware(req, res, next, false, false, true);
const authenticate_noerror_WithUser = (req, res, next) => authenticateMiddleware(req, res, next, true, false, true);
const authenticate_noerror_WithUserLean = (req, res, next) => {
  return authenticateMiddleware(req, res, next, true, true, true);
}

module.exports = {
  authenticate,
  authenticate_noerror,
  auth_default,
  authenticate_withUser,
  authenticate_noerror_WithUser,
  authenticate_noerror_WithUserLean,
};
