// src/client/shared/lib/useAutoLogout.ts
// Авторазлогин по политикам сессии роли

import { ref, onMounted, onUnmounted } from 'vue';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import { api } from '../api/api.client';
import { socketService } from '../api/SocketService';

dayjs.extend(utc);
dayjs.extend(timezone);

interface SessionPolicy {
  logoutTime: string | null;
  inactivityTimeout: number | null;
  sessionDuration: number | null;
}

const ACTIVITY_EVENTS = ['mousedown', 'keydown', 'scroll', 'touchstart'] as const;
const DEBOUNCE_MS = 1000;
const HEARTBEAT_MS = 30_000;

function performLogout(reason: string) {
  window.clearUser?.();
  window.location.href = `/login?reason=${encodeURIComponent(reason)}`;
}

export function useAutoLogout() {
  const policy = ref<SessionPolicy | null>(null);
  let inactivityTimer: ReturnType<typeof setTimeout> | null = null;
  let sessionTimer: ReturnType<typeof setInterval> | null = null;
  let heartbeatTimer: ReturnType<typeof setInterval> | null = null;
  let logoutTimeTimer: ReturnType<typeof setInterval> | null = null;
  let loginTime: number | null = null;
  let unsubKill: (() => void) | null = null;
  let activityDebounce: ReturnType<typeof setTimeout> | null = null;

  function resetInactivityTimer() {
    if (!policy.value?.inactivityTimeout) return;

    if (inactivityTimer) clearTimeout(inactivityTimer);
    inactivityTimer = setTimeout(() => {
      performLogout('inactivity');
    }, policy.value.inactivityTimeout * 60 * 1000);
  }

  function onActivity() {
    if (activityDebounce) clearTimeout(activityDebounce);
    activityDebounce = setTimeout(() => {
      resetInactivityTimer();
    }, DEBOUNCE_MS);
  }

  function startSessionTimer() {
    if (!policy.value?.sessionDuration || !loginTime) return;

    sessionTimer = setInterval(() => {
      const elapsed = (Date.now() - loginTime!) / 1000 / 60;
      if (elapsed >= policy.value!.sessionDuration!) {
        performLogout('session_expired');
      }
    }, 60_000);
  }

  function startHeartbeat() {
    heartbeatTimer = setInterval(() => {
      api.post('/auth/heartbeat', {}).catch(() => {});
    }, HEARTBEAT_MS);
  }

  function startLogoutTimeChecker() {
    if (!policy.value?.logoutTime || !loginTime) return;

    const loginHHmm = dayjs(loginTime).tz('Europe/Moscow').format('HH:mm');

    if (loginHHmm >= policy.value!.logoutTime!) return;

    const check = () => {
      const currentHHmm = dayjs().tz('Europe/Moscow').format('HH:mm');

      if (currentHHmm >= policy.value!.logoutTime!) {
        performLogout('time_limit');
      }
    };

    logoutTimeTimer = setInterval(check, 60_000);
    check();
  }

  function cleanup() {
    ACTIVITY_EVENTS.forEach((evt) => window.removeEventListener(evt, onActivity));
    if (inactivityTimer) clearTimeout(inactivityTimer);
    if (sessionTimer) clearInterval(sessionTimer);
    if (heartbeatTimer) clearInterval(heartbeatTimer);
    if (logoutTimeTimer) clearInterval(logoutTimeTimer);
    if (activityDebounce) clearTimeout(activityDebounce);
    if (unsubKill) unsubKill();
  }

  onMounted(async () => {
    try {
      const data = await api.get<SessionPolicy>('/system/session-policies/my');
      if (!data) return;

      policy.value = data;
      loginTime = Date.now();

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

      if (data.inactivityTimeout) resetInactivityTimer();
      if (data.sessionDuration) startSessionTimer();
      startHeartbeat();
      startLogoutTimeChecker();

      unsubKill = socketService.subscribe<{ reason: string }>('session:kill', () => {
        performLogout('server_kick');
      });
    } catch {
      // Не удалось загрузить политику — сессия без ограничений
    }
  });

  onUnmounted(cleanup);
}
