import axios, { AxiosRequestConfig } from 'axios';
import Constants from 'expo-constants';
import { fetch, FetchRequestInit } from 'expo/fetch';
import { Platform } from 'react-native';
import { type AccessToken } from './auth';

const { api: apiConfig, jsVersion } = require('@/config.json') as AppConfig;
let accessToken: AccessToken | undefined | null = null;

export function setAccessToken(token?: AccessToken | null) {

    accessToken = token;
}

export function getAccessToken() {
    if (!accessToken) {
        return null;
    }
    const now = Date.now() / 1000;
    if (accessToken.expiresAt < now - 30) {
        accessToken = null;
    }
    return accessToken;
}




export class HttpError extends Error {
    public get data() {
        return this._data;
    }
    // name: string = 'HttpError';
    constructor(message: string, public code: number, private _data?: any) {
        super(`${code} ${message}`);
    }

    toString() {
        return this.message;
    }

    static is(err: any) {
        return err instanceof ApiError ? err as ApiError : null;
    }
    static is5xx(err: any) {
        return err instanceof ApiError && err.code >= 500 && err.code < 600 ? err as ApiError : null;
    }
    static is4xx(err: any) {
        return err instanceof ApiError && err.code >= 400 && err.code < 500 ? err as ApiError : null;
    }
    static is3xx(err: any) {
        return err instanceof ApiError && err.code >= 300 && err.code < 400 ? err as ApiError : null;
    }

    static isApiError(err: any) {
        return err instanceof ApiError;
    }
}


export class ApiError extends HttpError {
    name: string = 'ApiError';

}


interface ApiResponse<T> {
    code?: number;
    msg?: string;
    data?: T;
}

export interface ListResponse<T = unknown> {
    start?: number;
    size?: string;
    list: T[];
}

const verString = (() => {
    const expoConfig = Constants.expoConfig;
    const versionName = expoConfig?.version || '';
    const platformSpecific = Platform.OS === 'android' ? expoConfig?.android?.versionCode || '' : expoConfig?.ios?.buildNumber || '';
    return `${versionName}(${platformSpecific})-${jsVersion}`;
})();
const apiClient = axios.create({
    baseURL: apiConfig.url,
    timeout: apiConfig.timeout || 10000,

    headers: {
        "x-app-name": Constants.expoConfig?.slug || 'unknown',
        "x-app-version": verString,
        "x-app-platform": Platform.OS,
        'Content-Type': 'application/json'
    },

    validateStatus: (status) => {
        return status > 199 && status < 500;
    },

});

// 开发模式下输出请求和响应数据
if (__DEV__) {
    // 请求拦截器：输出请求信息
    apiClient.interceptors.request.use(
        (config) => {
            console.log('📤 API 请求:', {
                url: config.url,
                method: config.method?.toUpperCase(),
                baseURL: config.baseURL,
                headers: config.headers,
                params: config.params,
                data: config.data,
            });
            return config;
        },
        (error) => {
            console.log('❌ API 请求配置错误:', error);
            return Promise.reject(error);
        }
    );

    // 响应拦截器：输出响应数据
    apiClient.interceptors.response.use(
        (response) => {
            console.log('📡 API 响应:', {
                url: response.config.url,
                method: response.config.method?.toUpperCase(),
                status: response.status,
                statusText: response.statusText,
                headers: response.headers,
                data: response.data,
            });
            return response;
        },
        (error) => {
            if (error.response) {
                console.log('❌ API 错误响应:', {
                    url: error.config?.url,
                    method: error.config?.method?.toUpperCase(),
                    status: error.response.status,
                    statusText: error.response.statusText,
                    headers: error.response.headers,
                    data: error.response.data,
                });
            } else if (error.request) {
                console.log('❌ API 请求错误:', {
                    message: error.message,
                    request: error.request,
                });
            } else {
                console.log('❌ API 错误:', error.message);
            }
            return Promise.reject(error);
        }
    );
}

type Options = Omit<AxiosRequestConfig, 'headers'> & { headers?: Record<string, any> };
async function request<T>(url: string, method: 'get' | 'post' | 'put' | 'delete', data?: any, config?: Options): Promise<T> {
    const headers: Record<string, string> = {
        'Content-Type': 'application/json',
        ...config?.headers
    };

    let token = getAccessToken();
    if (token?.token) {
        headers['Authorization'] = `Bearer ${token.token}`;
    }
    try {
        const response = await apiClient.request<ApiResponse<T>>({
            url,
            method,
            data,
            ...config,
            headers,
        });
        if (200 !== response.status) {
            throw new HttpError(response.statusText || 'http error', response.status);
        }
        const res = response.data;


        if (`${res?.code}` !== '1') {
            throw new ApiError(res?.msg || response.statusText, res?.code || 0, res?.data);
        }
        return res?.data as T;
    } catch (error) {
        if (error instanceof ApiError || error instanceof HttpError) {
            throw error;
        }
        // @ts-ignore
        throw new HttpError(error?.message || (`${error}`) || "unknown error", NaN);
    }
}
const rawRequest = async <T>(req: AxiosRequestConfig) => {

    const headers: Record<string, string> = {
        ...req.headers as any,
        "x-app-name": Constants.expoConfig?.slug || 'unknown',
        "x-app-version": verString,
        "x-app-platform": Platform.OS,
    };
    let token = getAccessToken();
    if (token?.token) {
        headers['Authorization'] = `Bearer ${token.token}`;
    }

    const res = await axios.request<T>({
        ...req,
        timeout: apiConfig.timeout || 10000,
        headers
    });
    if (res.status !== 200) {
        throw new HttpError(res.statusText, res.status, res.data as string);
    }
    return res;
}

async function uploadFile<T>(url: string, config?: FetchRequestInit): Promise<T> {
    const headers: Record<string, any> = {
        // 'Content-Type': 'multipart/form-data',
        ...config?.headers,
    };
    const token = getAccessToken();
    if (token?.token) {
        headers['Authorization'] = `Bearer ${token.token}`;
    }
    const result = await fetch(`${apiConfig.url}${url}`, {
        method: 'POST',
        ... config,
        headers
    });
    console.log('上传文件响应状态:', result);
    if (result.status !== 200) {
        throw new HttpError((await result.bytes()).toString(), result.status);
    }
    const res = await result.json() as ApiResponse<T>;
    if (`${res?.code}` !== '1') {
        throw new ApiError(res?.msg || 'upload error', res?.code || 0, res?.data);
    }
    return res.data as T;
}


async function get<T>(api: string, params?: Record<string, any>): Promise<T> {
    return await request<T>(api, 'get', undefined, { params });
}

async function post<T>(api: string, data?: any, config?: Options): Promise<T> {
    return await request<T>(api, 'post', data, config);
}

async function put<T>(api: string, data?: any, config?: Options): Promise<T> {
    return await request<T>(api, 'put', data, config);
}

async function deleted<T>(api: string, config?: Options): Promise<T> {
    return await request<T>(api, 'delete', undefined, config);
}
const api = {
    post, get, put, deleted, request, rawRequest, uploadFile
}


export default api;