// @ts-nocheck
// Disable TypeScript checking for this file due to CapacitorHttp/axios type incompatibilities
import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios';
import { Capacitor } from '@capacitor/core';
import { CapacitorHttp, HttpOptions, HttpResponse } from '@capacitor/core';

// Detect if running in Capacitor native environment
const isCapacitor = Capacitor.isNativePlatform();

// Production API URL for native app, relative URL for web
const API_BASE_URL = isCapacitor
    ? 'https://veridian.runfoo.run/api'
    : (import.meta.env.VITE_API_URL || '/api');

// Retry configuration
const MAX_RETRIES = 3;
const RETRY_DELAY_BASE = 1000; // 1 second

// Request queue for offline mode
let isRefreshing = false;
let failedQueue: Array<{
    resolve: (value?: unknown) => void;
    reject: (reason?: unknown) => void;
}> = [];

const processQueue = (error: unknown = null) => {
    failedQueue.forEach(prom => {
        if (error) {
            prom.reject(error);
        } else {
            prom.resolve();
        }
    });
    failedQueue = [];
};

// Helper to get auth token
const getAuthToken = (): string | null => {
    return localStorage.getItem('token');
};

// CapacitorHttp-based API client for native platforms
class CapacitorApiClient {
    private baseURL: string;

    constructor(baseURL: string) {
        this.baseURL = baseURL;
    }

    private async request<T>(method: string, url: string, data?: unknown, retryCount = 0): Promise<{ data: T; status: number }> {
        const fullUrl = url.startsWith('http') ? url : `${this.baseURL}${url}`;
        const token = getAuthToken();

        const options: HttpOptions = {
            url: fullUrl,
            method: method as HttpOptions['method'],
            headers: {
                'Content-Type': 'application/json',
                ...(token ? { Authorization: `Bearer ${token}` } : {}),
            },
            ...(data ? { data } : {}),
        };

        try {
            const response: HttpResponse = await CapacitorHttp.request(options);

            // Handle 401 Unauthorized - token expired
            if (response.status === 401) {
                if (isRefreshing) {
                    return new Promise((resolve, reject) => {
                        failedQueue.push({ resolve, reject });
                    }).then(() => this.request<T>(method, url, data));
                }

                isRefreshing = true;

                try {
                    const refreshToken = localStorage.getItem('refreshToken');
                    if (refreshToken) {
                        const refreshResponse = await CapacitorHttp.post({
                            url: `${this.baseURL}/auth/refresh`,
                            headers: { 'Content-Type': 'application/json' },
                            data: { refreshToken },
                        });

                        if (refreshResponse.status === 200) {
                            localStorage.setItem('token', refreshResponse.data.accessToken);
                            if (refreshResponse.data.refreshToken) {
                                localStorage.setItem('refreshToken', refreshResponse.data.refreshToken);
                            }
                            processQueue();
                            return this.request<T>(method, url, data);
                        }
                    }
                } catch (refreshError) {
                    processQueue(refreshError);
                    localStorage.removeItem('token');
                    localStorage.removeItem('refreshToken');
                    localStorage.removeItem('user');
                    window.location.href = '/login';
                    throw refreshError;
                } finally {
                    isRefreshing = false;
                }
            }

            // Handle errors (4xx, 5xx)
            if (response.status >= 400) {
                const shouldRetry = response.status >= 500 && response.status < 600;

                if (shouldRetry && retryCount < MAX_RETRIES) {
                    const delay = RETRY_DELAY_BASE * Math.pow(2, retryCount);
                    await new Promise(resolve => setTimeout(resolve, delay));
                    console.log(`Retrying request (${retryCount + 1}/${MAX_RETRIES}):`, url);
                    return this.request<T>(method, url, data, retryCount + 1);
                }

                // Handle rate limiting
                if (response.status === 429) {
                    window.dispatchEvent(new CustomEvent('api:rate-limited', {
                        detail: { waitTime: 60000, url }
                    }));
                }

                const error = new Error(response.data?.message || `HTTP ${response.status}`);
                (error as any).response = { status: response.status, data: response.data };
                throw error;
            }

            return { data: response.data as T, status: response.status };
        } catch (networkError: any) {
            // Network error - retry
            if (!networkError.response && retryCount < MAX_RETRIES) {
                const delay = RETRY_DELAY_BASE * Math.pow(2, retryCount);
                await new Promise(resolve => setTimeout(resolve, delay));
                console.log(`Retrying request due to network error (${retryCount + 1}/${MAX_RETRIES}):`, url);
                return this.request<T>(method, url, data, retryCount + 1);
            }
            throw networkError;
        }
    }

    get<T>(url: string) {
        return this.request<T>('GET', url);
    }

    post<T>(url: string, data?: unknown) {
        return this.request<T>('POST', url, data);
    }

    put<T>(url: string, data?: unknown) {
        return this.request<T>('PUT', url, data);
    }

    patch<T>(url: string, data?: unknown) {
        return this.request<T>('PATCH', url, data);
    }

    delete<T>(url: string) {
        return this.request<T>('DELETE', url);
    }
}

// Create the appropriate client based on platform
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let api: any;

if (isCapacitor) {
    // Use CapacitorHttp for native platforms
    api = new CapacitorApiClient(API_BASE_URL);
} else {
    // Use axios for web
    const axiosInstance = axios.create({
        baseURL: API_BASE_URL,
        headers: {
            'Content-Type': 'application/json',
        },
        timeout: 30000,
    });

    // Request interceptor - add auth token
    axiosInstance.interceptors.request.use((config) => {
        const token = localStorage.getItem('token');
        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
    });

    // Response interceptor - handle errors and retries
    axiosInstance.interceptors.response.use(
        (response) => response,
        async (error: AxiosError) => {
            const originalRequest = error.config as InternalAxiosRequestConfig & { _retryCount?: number };

            if (!originalRequest) {
                return Promise.reject(error);
            }

            // Handle 401 Unauthorized - token expired
            if (error.response?.status === 401) {
                if (isRefreshing) {
                    return new Promise((resolve, reject) => {
                        failedQueue.push({ resolve, reject });
                    }).then(() => axiosInstance(originalRequest));
                }

                isRefreshing = true;

                try {
                    const refreshToken = localStorage.getItem('refreshToken');
                    if (refreshToken) {
                        const { data } = await axios.post(
                            `${API_BASE_URL}/auth/refresh`,
                            { refreshToken }
                        );

                        localStorage.setItem('token', data.accessToken);
                        if (data.refreshToken) {
                            localStorage.setItem('refreshToken', data.refreshToken);
                        }

                        processQueue();
                        return axiosInstance(originalRequest);
                    }
                } catch (refreshError) {
                    processQueue(refreshError);
                    localStorage.removeItem('token');
                    localStorage.removeItem('refreshToken');
                    localStorage.removeItem('user');
                    window.location.href = '/login';
                    return Promise.reject(refreshError);
                } finally {
                    isRefreshing = false;
                }
            }

            // Retry logic for network errors and 5xx errors
            const shouldRetry = (
                !error.response ||
                (error.response.status >= 500 && error.response.status < 600)
            );

            if (shouldRetry) {
                originalRequest._retryCount = originalRequest._retryCount || 0;

                if (originalRequest._retryCount < MAX_RETRIES) {
                    originalRequest._retryCount++;
                    const delay = RETRY_DELAY_BASE * Math.pow(2, originalRequest._retryCount - 1);
                    await new Promise(resolve => setTimeout(resolve, delay));
                    console.log(`Retrying request (${originalRequest._retryCount}/${MAX_RETRIES}):`, originalRequest.url);
                    return axiosInstance(originalRequest);
                }
            }

            // Handle rate limiting (429)
            if (error.response?.status === 429) {
                const retryAfter = error.response.headers['retry-after'];
                const waitTime = retryAfter ? parseInt(retryAfter as string, 10) * 1000 : 60000;
                window.dispatchEvent(new CustomEvent('api:rate-limited', {
                    detail: { waitTime, url: originalRequest.url }
                }));
            }

            return Promise.reject(error);
        }
    );

    api = axiosInstance;
}

export default api;
