// frontend/src/services/api.ts

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';

const getBackendHost = (): string => {
    const host: string = window.location.hostname || 'localhost';
    return window.location.protocol === 'https:' ? host : `${host}:8000`;
};

export const API_BASE: string = `${window.location.protocol}//${getBackendHost()}/api`;
export const WS_URL: string = `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${getBackendHost()}/api/ws`;

export const getToken = (): string | null => localStorage.getItem('volleyToken');

const api = {
    request: async <T>(
        method: HttpMethod,
        url: string,
        data: unknown = null,
        isFormData: boolean = false
    ): Promise<T> => {
        const headers: Record<string, string> = {};
        const token = getToken();

        if (token) headers['Authorization'] = `Bearer ${token}`;
        if (!isFormData) headers['Content-Type'] = 'application/json';

        const opts: RequestInit = {
            method,
            headers
        };

        if (data) {
            opts.body = isFormData ? (data as FormData) : JSON.stringify(data);
        }

        // Ensure clean URL concatenation
        const baseUrl = API_BASE.replace(/\/$/, '');
        const endpoint = url.startsWith('/') ? url : `/${url}`;

        const res = await fetch(`${baseUrl}${endpoint}`, opts);

        if (!res.ok) {
            if (res.status === 401) {
                localStorage.removeItem('volleyToken');
                if (window.location.pathname !== '/login') {
                    window.location.href = '/login';
                }
            }
            // Attempt to parse error detail, fallback to generic message
            const errorData = await res.json().catch(() => ({ detail: 'An error occurred' }));
            throw errorData;
        }

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

    get: <T>(url: string) => api.request<T>('GET', url),
    post: <T>(url: string, data?: unknown) => api.request<T>('POST', url, data),
    postForm: <T>(url: string, data: FormData) => api.request<T>('POST', url, data, true),
    put: <T>(url: string, data?: unknown) => api.request<T>('PUT', url, data),
    patch: <T>(url: string, data?: unknown) => api.request<T>('PATCH', url, data),
    delete: <T>(url: string) => api.request<T>('DELETE', url)
};

export default api;