import Request from 'luch-request';
import { getCache } from '@/utils/cache';
import { clearSession } from '@/utils/session';

/**
 * 灵犀学 AI 通用 HTTP 客户端（基于 luch-request）
 *
 * - 自动注入 Bearer Token
 * - 自动注入租户头 x-tenant-id
 * - code !== 200 全局 toast 错误信息
 * - 401 自动清缓存并跳转登录
 * - 网络异常时弹窗提示
 */

const HOST = (import.meta.env.VITE_BASE_URL as string) || '';
const BASE_URL = `${HOST}/api/main`;
const TENANT_ID = '1966391196339204098';
let isReloginHandling = false;

interface BackendResp<T = any> {
    code: number;
    data: T;
    message?: string;
    msg?: string;
    [key: string]: any;
}

export class HttpError extends Error {
    code: number;
    data: any;
    constructor(message: string, code: number, data?: any) {
        super(message);
        this.code = code;
        this.data = data;
    }
}

const http = new Request({
    baseURL: BASE_URL,
    timeout: 30000,
    header: {
        'Content-Type': 'application/json;charset=UTF-8',
        'x-tenant-id': TENANT_ID,
    },
});

const LOGIN_URL = '/pages/login/index';

const goLoginPage = () => {
    uni.reLaunch({
        url: LOGIN_URL,
        fail: () => {
            uni.redirectTo({ url: LOGIN_URL });
        },
        complete: () => {
            isReloginHandling = false;
        },
    });
};

export const handleUnauthorized = (message = '登录已失效，请重新登录') => {
    if (isReloginHandling) return;
    isReloginHandling = true;

    clearSession();

    // 小程序中 showToast 期间 navigate 可能被拦截，先跳转再提示
    goLoginPage();
    setTimeout(() => {
        uni.showToast({ title: message, icon: 'none', duration: 2500 });
    }, 100);
};

const isUnauthorizedCode = (code: unknown) => Number(code) === 401;

const normalizeResponseData = (raw: unknown): BackendResp | null => {
    if (!raw) return null;
    if (typeof raw === 'object') return raw as BackendResp;
    if (typeof raw === 'string') {
        try {
            const parsed = JSON.parse(raw);
            return parsed && typeof parsed === 'object' ? (parsed as BackendResp) : null;
        } catch {
            return null;
        }
    }
    return null;
};

// ----------- 请求拦截 -----------
http.interceptors.request.use(
    (config) => {
        const token = getCache('token');
        if (token && config.header) {
            // 默认带上 Authorization；接口可显式覆盖（传空字符串以匿名调用）
            if (!('Authorization' in config.header)) {
                (config.header as any).Authorization = `Bearer ${token}`;
            }
        }
        // 始终携带租户 ID
        if (config.header && !('x-tenant-id' in config.header)) {
            (config.header as any)['x-tenant-id'] = TENANT_ID;
        }
        return config;
    },
    (err) => Promise.reject(err),
);

// ----------- 响应拦截 -----------
http.interceptors.response.use(
    (response: any) => {
        const data = normalizeResponseData(response.data);
        if (!data) {
            return response;
        }

        // 兼容不同后端返回规范：部分接口成功码为 0（并可能带 success=true）
        if (data.code === 200 || data.code === 0) {
            return data;
        }

        if (isUnauthorizedCode(data.code)) {
            const msg401 = data.message || data.msg || '登录已失效，请重新登录';
            handleUnauthorized(msg401);
            return Promise.reject(new HttpError(msg401, 401, data));
        }

        // 业务错误
        const msg = data.message || data.msg || '请求失败';
        if (!(response.config as any)?.silent) {
            uni.showToast({ title: msg, icon: 'none', duration: 2500 });
        }
        return Promise.reject(new HttpError(msg, data.code, data));
    },
    (err: any) => {
        const body = normalizeResponseData(err?.data);
        const status = err?.statusCode || err?.status;
        let msg = body?.message || body?.msg || err?.errMsg || err?.message || '网络异常';

        if (isUnauthorizedCode(status) || isUnauthorizedCode(body?.code)) {
            msg = body?.message || body?.msg || '登录已失效，请重新登录';
            handleUnauthorized(msg);
            return Promise.reject(new HttpError(msg, 401, body || err));
        }

        if (status === 500) {
            msg = '服务异常，请稍后重试';
        }

        uni.showToast({ title: msg, icon: 'none', duration: 2500 });
        return Promise.reject(new HttpError(msg, status || -1, err));
    },
);

/**
 * 默认导出 luch-request 实例
 * 同时暴露通用调用方法，兼容老接口的 `request({ url, method, data, params, headers })` 风格
 */
export interface RequestOptions {
    url: string;
    method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
    data?: anyObj;
    params?: anyObj;
    headers?: anyObj;
    silent?: boolean;
}

export const request = <T = any>(opt: RequestOptions): Promise<BackendResp<T>> => {
    const cfg: any = {
        url: opt.url,
        method: opt.method || 'GET',
        custom: { silent: opt.silent },
    };
    if (opt.headers) cfg.header = opt.headers;
    if (cfg.method === 'GET') {
        cfg.params = opt.params || opt.data;
    } else {
        cfg.data = opt.data;
        if (opt.params) cfg.params = opt.params;
    }
    if (opt.silent) cfg.silent = true;
    return http.request(cfg) as Promise<BackendResp<T>>;
};

export default request;
export { http, HOST, BASE_URL, TENANT_ID };
