import axios, { type AxiosInstance } from 'axios';

/**
 * Axios-инстанс для API-запросов.
 *
 * Sanctum SPA mode (см. `bootstrap/app.php` + `routes/web.php` § /api/auth/*):
 * 1. `withCredentials: true` — отправляем session-cookie + XSRF-TOKEN cookie.
 * 2. `withXSRFToken: true` — axios читает XSRF-TOKEN cookie и кладёт
 *    в `X-XSRF-TOKEN` header автоматически (Laravel валидирует CSRF).
 * 3. На первый запрос — `await ensureCsrfCookie()` забирает CSRF-cookie через
 *    `GET /sanctum/csrf-cookie` (выставляется один раз за сессию).
 *
 * baseURL не указываем — используем относительные пути (`/api/auth/login`),
 * браузер шлёт same-origin → cookie работают без CORS-настроек.
 */
export const apiClient: AxiosInstance = axios.create({
    withCredentials: true,
    withXSRFToken: true,
    headers: {
        Accept: 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
    },
});

let csrfCookieFetched = false;

export async function ensureCsrfCookie(): Promise<void> {
    if (csrfCookieFetched) return;
    await apiClient.get('/sanctum/csrf-cookie');
    csrfCookieFetched = true;
}

/**
 * Хелпер для обработки validation-error 422 от Laravel.
 * Возвращает `{ field: [messages] }` или null.
 */
export function extractValidationErrors(error: unknown): Record<string, string[]> | null {
    if (!axios.isAxiosError(error)) return null;
    if (error.response?.status !== 422) return null;
    const data = error.response.data as { errors?: Record<string, string[]> };
    return data.errors ?? null;
}

/**
 * Хелпер для general error-message (любая ошибка → human-readable строка).
 */
export function extractErrorMessage(error: unknown, fallback = 'Произошла ошибка. Попробуйте позже.'): string {
    if (axios.isAxiosError(error)) {
        const data = error.response?.data as { message?: string } | undefined;
        if (data?.message) return data.message;
        if (error.response?.status === 401) return 'Требуется вход.';
        if (error.response?.status === 403) return 'Нет прав на это действие.';
        if (error.response?.status === 500) return 'Внутренняя ошибка сервера.';
    }
    return fallback;
}

/**
 * Хелпер для 429 Too Many Requests (ТЗ §22.4.4: 5 попыток / 15 мин).
 * Возвращает retry_after в секундах или null для других ошибок.
 *
 * Backend кладёт `retry_after: number` в JSON и `Retry-After` в headers
 * (см. AuthController::lockoutResponse).
 */
export function extractRateLimitRetry(error: unknown): number | null {
    if (!axios.isAxiosError(error)) return null;
    if (error.response?.status !== 429) return null;
    const data = error.response.data as { retry_after?: number } | undefined;
    if (typeof data?.retry_after === 'number') return data.retry_after;
    const header = error.response.headers['retry-after'];
    if (header) return parseInt(String(header), 10) || null;
    return null;
}
