import { auth } from './auth.js';

const SESSION_TIMEOUT_MS = Number(import.meta.env.VITE_SESSION_TIMEOUT_MS || 15 * 60 * 1000);
const SESSION_WARNING_MS = Number(import.meta.env.VITE_SESSION_WARNING_MS || 60 * 1000);

let inactivityTimer = null;
let warningTimer = null;
let warningCountdownTimer = null;
let warningEndsAt = null;
let warningOverlay = null;
let hasInitialized = false;
let fetchIsPatched = false;

function isAuthenticated() {
  return Boolean(localStorage.getItem('token'));
}

function clearTimers() {
  if (inactivityTimer) {
    clearTimeout(inactivityTimer);
    inactivityTimer = null;
  }

  if (warningTimer) {
    clearTimeout(warningTimer);
    warningTimer = null;
  }

  if (warningCountdownTimer) {
    clearInterval(warningCountdownTimer);
    warningCountdownTimer = null;
  }
}

function removeWarningOverlay() {
  if (warningOverlay) {
    warningOverlay.remove();
    warningOverlay = null;
  }
  warningEndsAt = null;
  if (warningCountdownTimer) {
    clearInterval(warningCountdownTimer);
    warningCountdownTimer = null;
  }
}

function getRemainingSeconds() {
  if (!warningEndsAt) return 0;
  return Math.max(0, Math.ceil((warningEndsAt - Date.now()) / 1000));
}

function forceSessionExpiration(message = 'Tu sesion ha expirado. Inicia sesion de nuevo.') {
  removeWarningOverlay();
  clearTimers();
  auth.logout();
  sessionStorage.setItem('session-expired-message', message);
  window.location.hash = '#login';
}

function showWarningOverlay() {
  if (!isAuthenticated()) return;

  removeWarningOverlay();

  const overlay = document.createElement('div');
  overlay.className = 'session-warning-overlay';
  overlay.innerHTML = `
    <div class="session-warning-modal" role="dialog" aria-modal="true" aria-labelledby="session-warning-title">
      <h3 id="session-warning-title">Tu sesion va a expirar</h3>
      <p>Por inactividad, se cerrara tu sesion automaticamente en <strong id="session-warning-countdown"></strong>.</p>
      <div class="session-warning-actions">
        <button type="button" class="session-warning-logout">Cerrar sesion ahora</button>
        <button type="button" class="session-warning-continue">Seguir conectado</button>
      </div>
    </div>
  `;

  const continueBtn = overlay.querySelector('.session-warning-continue');
  const logoutBtn = overlay.querySelector('.session-warning-logout');
  const countdownEl = overlay.querySelector('#session-warning-countdown');

  continueBtn?.addEventListener('click', () => {
    removeWarningOverlay();
    resetSessionTimers();
  });

  logoutBtn?.addEventListener('click', () => {
    forceSessionExpiration('Sesion finalizada por inactividad.');
  });

  warningEndsAt = Date.now() + SESSION_WARNING_MS;

  const updateCountdown = () => {
    const seconds = getRemainingSeconds();
    const mins = String(Math.floor(seconds / 60)).padStart(2, '0');
    const secs = String(seconds % 60).padStart(2, '0');
    if (countdownEl) {
      countdownEl.textContent = `${mins}:${secs}`;
    }

    if (seconds <= 0) {
      forceSessionExpiration();
    }
  };

  updateCountdown();
  warningCountdownTimer = setInterval(updateCountdown, 1000);

  warningOverlay = overlay;
  document.body.appendChild(overlay);
}

function resetSessionTimers() {
  clearTimers();

  if (!isAuthenticated()) {
    removeWarningOverlay();
    return;
  }

  const warningDelay = Math.max(SESSION_TIMEOUT_MS - SESSION_WARNING_MS, 1000);
  warningTimer = setTimeout(showWarningOverlay, warningDelay);
  inactivityTimer = setTimeout(() => forceSessionExpiration(), SESSION_TIMEOUT_MS);
}

function patchFetchFor401AndActivity() {
  if (fetchIsPatched) return;

  const originalFetch = window.fetch.bind(window);

  window.fetch = async (...args) => {
    const requestUrl = typeof args[0] === 'string' ? args[0] : (args[0]?.url || '');
    const isLoginEndpoint = requestUrl.includes('/api/Auth/login');

    if (!isLoginEndpoint && isAuthenticated()) {
      resetSessionTimers();
    }

    const response = await originalFetch(...args);

    if (response.status === 401 && !isLoginEndpoint && isAuthenticated()) {
      forceSessionExpiration('Tu sesion ha expirado o ya no es valida. Inicia sesion de nuevo.');
    }

    return response;
  };

  fetchIsPatched = true;
}

function bindActivityListeners() {
  const events = ['mousemove', 'mousedown', 'keydown', 'touchstart', 'scroll'];

  const onActivity = () => {
    if (isAuthenticated()) {
      resetSessionTimers();
    }
  };

  events.forEach(eventName => {
    window.addEventListener(eventName, onActivity, { passive: true });
  });
}

function bindAuthListeners() {
  window.addEventListener('auth:login', () => {
    removeWarningOverlay();
    resetSessionTimers();
  });

  window.addEventListener('auth:logout', () => {
    removeWarningOverlay();
    clearTimers();
  });
}

export function initSessionManager() {
  if (hasInitialized) return;

  patchFetchFor401AndActivity();
  bindActivityListeners();
  bindAuthListeners();
  resetSessionTimers();

  hasInitialized = true;
}
