import axios from 'axios';
import { toast } from 'sonner';

window.axios = axios;

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

// Configure CSRF token for all axios requests
const token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.getAttribute('content');
}

// Configure axios to send credentials (cookies) with requests
window.axios.defaults.withCredentials = true;

// Laravel Inertia uses X-CSRF-TOKEN from meta tag (set in blade template)
// The session cookie is http-only, so we disable axios's automatic XSRF handling
// and use X-CSRF-TOKEN header which is the Laravel standard
(window.axios.defaults as any).xsrfCookieName = null;
(window.axios.defaults as any).xsrfHeaderName = null;

// Helper function to get CSRF token
export function getCsrfToken(): string | null {
    const metaTag = document.head.querySelector('meta[name="csrf-token"]');
    return metaTag?.getAttribute('content') || null;
}

// Helper function to update CSRF token
export function updateCsrfToken(newToken: string): void {
    const metaTag = document.head.querySelector('meta[name="csrf-token"]');
    if (metaTag) {
        metaTag.setAttribute('content', newToken);
    }
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = newToken;
}

// Flag to prevent multiple simultaneous refreshes
let isRefreshingCsrf = false;
let csrfRefreshPromise: Promise<string | null> | null = null;

// Function to refresh CSRF token by fetching a fresh one
export async function refreshCsrfToken(): Promise<string | null> {
    if (isRefreshingCsrf && csrfRefreshPromise) {
        return csrfRefreshPromise;
    }

    isRefreshingCsrf = true;
    csrfRefreshPromise = (async () => {
        try {
            // Fetch the current page to get a fresh CSRF token from meta tag
            const response = await fetch(window.location.href, {
                method: 'GET',
                credentials: 'include',
                headers: {
                    Accept: 'text/html',
                },
            });

            if (response.ok) {
                const html = await response.text();
                const match = html.match(/<meta[^>]*name="csrf-token"[^>]*content="([^"]+)"/);
                if (match && match[1]) {
                    updateCsrfToken(match[1]);
                    return match[1];
                }
            }
            return null;
        } catch {
            return null;
        } finally {
            isRefreshingCsrf = false;
            csrfRefreshPromise = null;
        }
    })();

    return csrfRefreshPromise;
}

// Axios interceptor to handle errors
window.axios.interceptors.response.use(
    (response) => response,
    async (error) => {
        const originalRequest = error.config;

        // Handle 429 Too Many Requests (Throttle)
        if (error.response?.status === 429) {
            const data = error.response.data;
            const message = data?.message || data?.toast?.message || 'Terlalu banyak permintaan. Silakan tunggu beberapa saat.';
            const retryAfter = data?.retry_after || 60;

            // Show toast notification
            toast.error(message, {
                duration: 5000,
                description: `Silakan coba lagi dalam ${retryAfter} detik`,
            });

            return Promise.reject(error);
        }

        // Handle 419 CSRF token mismatch
        if (error.response?.status === 419 && !originalRequest._retry) {
            originalRequest._retry = true;

            const newToken = await refreshCsrfToken();
            if (newToken) {
                // Update the original request with new token
                originalRequest.headers['X-CSRF-TOKEN'] = newToken;
                return window.axios(originalRequest);
            }

            // If token refresh failed, reload the page
            window.location.reload();
            return Promise.reject(error);
        }

        return Promise.reject(error);
    },
);
