class WxRequest {
    constructor(options = {}) {
        this.baseUrl = options.baseUrl || '';
        this.header = options.header || {};
        this.interceptors = {
            request: (config) => config,
            response: (response) => response
        };
    }

    /**
     * Set request interceptor
     * @param {Function} callback 
     */
    setRequestInterceptor(callback) {
        this.interceptors.request = callback;
    }

    /**
     * Set response interceptor
     * @param {Function} callback 
     */
    setResponseInterceptor(callback) {
        this.interceptors.response = callback;
    }

    /**
     * Core request method
     * @param {Object} options 
     */
    request(options = {}) {
        // Merge headers
        const header = { ...this.header, ...options.header };

        // Prepare config
        let config = {
            url: (options.url.startsWith('http') ? options.url : this.baseUrl + options.url),
            method: options.method || 'GET',
            data: options.data || {},
            header: header,
            timeout: options.timeout || 60000
        };

        // Apply request interceptor
        config = this.interceptors.request(config);

        return new Promise((resolve, reject) => {
            wx.request({
                ...config,
                success: (res) => {
                    // Apply response interceptor (pass the whole wx response)
                    const processedResponse = this.interceptors.response(res);
                    const { statusCode, data } = processedResponse;

                    // 1. Check HTTP Status Code
                    if (statusCode >= 200 && statusCode < 300) {
                        // 2. Check Business Logic Code (Assuming 200 is success based on common Go patterns, 
                        // matching the user's struct: Code, Data, Msg)
                        // If data.code exists, we check it. If not (maybe not JSON), we pass through or handle.
                        const businessCode = data.code;

                        // Strict check: if code is 200, success.
                        if (businessCode === 200) {
                            resolve(data.data); // Return the inner Data object
                        } else {
                            // Business logic error
                            this.handleError({
                                errMsg: data.msg || 'Error',
                                code: businessCode
                            });
                            reject(data);
                        }
                    } else {
                        // Handle non-200 HTTP errors
                        this.handleError({ errMsg: `HTTP Error: ${statusCode}`, ...res });
                        reject(res);
                    }
                },
                fail: (err) => {
                    this.handleError({ errMsg: 'Network Error', ...err });
                    reject(err);
                }
            });
        });
    }

    /**
     * Handle global errors (Toast)
     * @param {Object} error 
     */
    handleError(error) {
        const message = error.errMsg || error.msg || '请求失败，请稍后重试';
        wx.showToast({
            title: message,
            icon: 'none',
            duration: 3000
        });
        console.error('API Error:', error);
    }

    /**
     * Upload file
     * @param {string} filePath Local file path
     * @param {string} name Form field name (default: file)
     * @param {Object} formData Additional form data
     */
    upload(filePath, name = 'file', formData = {}) {
        // Prepare config
        let config = {
            url: this.baseUrl + '/oss/upload',
            header: { ...this.header }, // Copy default headers
            filePath: filePath,
            name: name,
            formData: formData
        };

        // Apply request interceptor (reuse logic for token injection)
        // Note: wx.uploadFile doesn't support method/data in the same way, but we use interceptor for header mainly
        config = this.interceptors.request(config);

        return new Promise((resolve, reject) => {
            wx.uploadFile({
                url: config.url,
                filePath: config.filePath,
                name: config.name,
                formData: config.formData,
                header: config.header,
                success: (res) => {
                    // wx.uploadFile returns data as String, need to parse
                    let data;
                    try {
                        data = JSON.parse(res.data);
                    } catch (e) {
                        data = { code: 500, msg: 'Response parse error', data: res.data };
                    }

                    // Reconstruct a response object for interceptor
                    const responseObj = { ...res, data: data };

                    // Apply response interceptor
                    const processedResponse = this.interceptors.response(responseObj);
                    const { statusCode, data: finalData } = processedResponse;

                    // Status Code check (uploadFile also returns statusCode)
                    if (statusCode >= 200 && statusCode < 300) {
                        const businessCode = finalData.code;
                        if (businessCode === 200) {
                            resolve(finalData.data);
                        } else {
                            this.handleError({
                                errMsg: finalData.msg || 'Upload Error',
                                code: businessCode
                            });
                            reject(finalData);
                        }
                    } else {
                        this.handleError({ errMsg: `HTTP Error: ${statusCode}`, ...res });
                        reject(res);
                    }
                },
                fail: (err) => {
                    this.handleError({ errMsg: 'Upload Network Error', ...err });
                    reject(err);
                }
            });
        });
    }

    get(url, data = {}, header = {}) {
        return this.request({ url, method: 'GET', data, header });
    }

    post(url, data = {}, header = {}) {
        return this.request({ url, method: 'POST', data, header });
    }
}

// Initialize with default instance
const request = new WxRequest({
    baseUrl: 'http://192.168.0.184:8888',
    header: {
        'Content-Type': 'application/json'
    }
});

// Example: Setup default interceptors
request.setRequestInterceptor((config) => {
    // Inject token if available
    const token = wx.getStorageSync('token');
    if (token) {
        // User requested: Bearer + token
        config.header['Authorization'] = `Bearer ${token}`;
    }
    return config;
});

request.setResponseInterceptor((response) => {
    // Handle global token expiration (e.g., HTTP 401 or Business Code 401)
    if (response.statusCode === 401 || response.data?.code === 401) {
        wx.removeStorageSync('token');
        // Redirect to login if needed, or just warn
        // wx.reLaunch({ url: '/pages/login/index' });
    }
    return response;
});

export default request;
export { WxRequest };
