import { useAuthStore } from '../stores/authStore';

const BASE_URL = '';

function getToken(): string | null {
  try {
    const raw = localStorage.getItem('clinicpro-auth');
    if (!raw) return null;
    const parsed = JSON.parse(raw);
    return parsed?.state?.token ?? null;
  } catch {
    return null;
  }
}

export class ApiError extends Error {
  constructor(
    public status: number,
    public code: string,
    message: string,
  ) {
    super(message);
  }
}

// چند درخواست همزمان که ۴۰۱ می‌گیرند، فقط یک‌بار refresh را اجرا کنند
let refreshPromise: Promise<string | null> | null = null;

function refreshOnce(): Promise<string | null> {
  if (!refreshPromise) {
    refreshPromise = useAuthStore.getState().refresh().finally(() => {
      refreshPromise = null;
    });
  }
  return refreshPromise;
}

async function request<T>(
  path: string,
  options: RequestInit = {},
  retry = true,
): Promise<T> {
  const token = getToken();
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...(options.headers as Record<string, string>),
  };
  if (token) headers['Authorization'] = `Bearer ${token}`;

  const res = await fetch(`${BASE_URL}${path}`, { ...options, headers });

  if (!res.ok) {
    if (res.status === 401) {
      // تلاش یک‌باره برای تازه‌سازی توکن، سپس اجرای مجدد همان درخواست
      if (retry) {
        const newToken = await refreshOnce();
        if (newToken) {
          return request<T>(path, options, false);
        }
      }
      useAuthStore.getState().logout();
      window.location.replace('/admin/login');
      throw new ApiError(401, 'ERR_UNAUTHORIZED', 'نشست منقضی شده است');
    }
    const body = await res.json().catch(() => ({}));
    const firstErr = body?.errors?.[0];
    throw new ApiError(
      res.status,
      firstErr?.code ?? 'ERR_UNKNOWN',
      firstErr?.message ?? 'خطای ناشناخته',
    );
  }

  return res.json() as Promise<T>;
}

export const api = {
  get: <T>(path: string) => request<T>(path),
  post: <T>(path: string, body: unknown) =>
    request<T>(path, { method: 'POST', body: JSON.stringify(body) }),
  patch: <T>(path: string, body: unknown) =>
    request<T>(path, { method: 'PATCH', body: JSON.stringify(body) }),
  put: <T>(path: string, body: unknown) =>
    request<T>(path, { method: 'PUT', body: JSON.stringify(body) }),
  delete: <T>(path: string) => request<T>(path, { method: 'DELETE' }),
  download: (path: string) => downloadFile(path),
};

// دانلود فایل با ارسال توکن JWT در هدر و ذخیره روی دیسک کاربر
async function downloadFile(path: string, retry = true): Promise<void> {
  const token = getToken();
  const headers: Record<string, string> = {};
  if (token) headers['Authorization'] = `Bearer ${token}`;

  const res = await fetch(`${BASE_URL}${path}`, { headers });

  if (!res.ok) {
    if (res.status === 401 && retry) {
      const newToken = await refreshOnce();
      if (newToken) return downloadFile(path, false);
      useAuthStore.getState().logout();
      window.location.replace('/admin/login');
    }
    throw new ApiError(res.status, 'ERR_DOWNLOAD', 'دانلود ناموفق بود');
  }

  const blob = await res.blob();
  const disposition = res.headers.get('Content-Disposition') ?? '';
  const match = disposition.match(/filename="?([^"]+)"?/);
  const filename = match ? match[1] : 'download';

  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  a.remove();
  URL.revokeObjectURL(url);
}

export interface ApiResponse<T> {
  success: boolean;
  data: T;
  errors: { code: string; message: string; field?: string }[];
}

export interface PaginatedResponse<T> {
  success: boolean;
  data: T[];
  meta: {
    totalRecords: number;
    totalPages: number;
    currentPage: number;
  };
  errors: [];
}
