import { API_BASE } from '@/lib/config';

let memoryToken: string | null = null;
let memoryRefreshToken: string | null = null;
let memoryAdminToken: string | null = null;
let initPromise: Promise<void> | null = null;

export function getToken(): string | null {
  return memoryToken;
}

export function getAdminToken(): string | null {
  return memoryAdminToken;
}

export function getRefreshToken(): string | null {
  return memoryRefreshToken;
}

export function setTokens(accessToken: string, refreshToken?: string) {
  memoryToken = accessToken;
  if (refreshToken) memoryRefreshToken = refreshToken;
}

export function clearTokens() {
  memoryToken = null;
  memoryRefreshToken = null;
}

export function setAdminToken(token: string) {
  memoryAdminToken = token;
}

export function clearAdminToken() {
  memoryAdminToken = null;
}

export function isLoggedIn(): boolean {
  return !!memoryToken;
}

export function isAdminLoggedIn(): boolean {
  return !!memoryAdminToken;
}

export async function initAuth(): Promise<void> {
  if (initPromise) return initPromise;
  if (typeof window === 'undefined') return;
  if (memoryToken) return;

  initPromise = (async () => {
    try {
      const res = await fetch(`${API_BASE}/auth/verify`, {
        credentials: 'include',
      });
      if (res.ok) {
        const data = await res.json();
        if (data.accessToken) memoryToken = data.accessToken;
        return;
      }
    } catch {
    }
  })();

  await initPromise;
  initPromise = null;
}

export async function adminApiFetch(url: string, opts: RequestInit = {}): Promise<Response> {
  const token = getAdminToken();
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(opts.headers as Record<string, string> || {}),
  };
  if (token) headers['Authorization'] = `Bearer ${token}`;
  return fetch(`${API_BASE}${url}`, { ...opts, headers });
}

export async function refreshToken(): Promise<string | null> {
  const token = getToken();
  const refreshTk = getRefreshToken();
  if (!token && !refreshTk) return null;

  try {
    const res = await fetch(`${API_BASE}/auth/refresh`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ accessToken: token }),
      credentials: 'include',
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.message);
    setTokens(data.accessToken, data.refreshToken);
    return data.accessToken;
  } catch {
    clearTokens();
    return null;
  }
}

export async function apiFetch(url: string, opts: RequestInit = {}): Promise<Response> {
  const token = getToken();
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(opts.headers as Record<string, string> || {}),
  };
  if (token) headers['Authorization'] = `Bearer ${token}`;

  let res = await fetch(`${API_BASE}${url}`, { ...opts, headers, credentials: 'include' });

  if (res.status === 401 && token) {
    const newToken = await refreshToken();
    if (newToken) {
      headers['Authorization'] = `Bearer ${newToken}`;
      res = await fetch(`${API_BASE}${url}`, { ...opts, headers, credentials: 'include' });
    }
  }

  return res;
}

export async function apiLogout(): Promise<void> {
  try {
    await fetch(`${API_BASE}/auth/logout`, { method: 'POST', credentials: 'include' });
  } catch {}
  clearTokens();
}
