import { ref, onUnmounted } from 'vue'
import { CommonResult } from '@/services/http/interface'
import { useDataTable } from '../datatable'

interface RequestOptions<TParams, TResponse> {
    params?: {
        page?: number; // 当前页码
        pagesize?: number; // 每页条数
    } & TParams;
    localPagination?: boolean;
    manual?: boolean; // 是否手动触发
    onBefore?: () => unknown;
    onSuccess?: (res: TResponse) => void;
    onError?: (err: string) => void;
    onFinally?: () => void;
}

// 判断对象是否通用响应对象
const isCommonResult = (obj: unknown): obj is CommonResult => {
    if (obj instanceof Object) {
        return 'code' in obj && 'data' in obj
    }
    return false
}

export function useRequest<TParams extends object, TResponse>(asyncFun: (params: TParams) => Promise<TResponse>, options?: RequestOptions<TParams, TResponse>) {
    const { params, localPagination, manual, onBefore, onSuccess, onError, onFinally } = options ?? {}

    type Result = TResponse extends CommonResult ? TResponse['data'] : TResponse // 获取返回值的类型
    type ResultType = Result extends (infer U)[] ? U : Result // 如果 U 是数组，取 U 的类型

    const { dataList, filters, total, pageIndex, pageSize, pageCount } = useDataTable<ResultType>({
        localPagination,
        pageIndex: params?.page,
        pageSize: params?.pagesize,
    })
    const data = ref<ResultType>()
    const loading = ref(false)

    // 异步函数
    const runAsync = async (payload: Partial<TParams> = {}) => {
        if (params && params.pagesize) {
            params.page = pageIndex.value
            params.pagesize = pageSize.value
        }
        onBefore && await onBefore()
        const res = await asyncFun({ ...params, ...payload } as TParams)
        if (isCommonResult(res)) {
            total.value = res.total
            if (Array.isArray(res.data)) {
                dataList.value = res.data
            } else {
                data.value = res.data as ResultType
            }
        } else {
            if (Array.isArray(res)) {
                dataList.value = res
            } else {
                data.value = res as ResultType
            }
        }
        return res
    }

    // 同步函数
    const run = (payload: Partial<TParams> = {}) => {
        loading.value = true
        runAsync(payload).then((res) => {
            onSuccess && onSuccess(res)
        }).catch((err) => {
            onError && onError(err)
        }).finally(() => {
            loading.value = false
            onFinally && onFinally()
        })
    }

    const cancel = () => {
        console.warn('取消请求')
    }

    if (!manual) {
        run() // 自动执行
    }

    onUnmounted(() => {
        cancel()
    })

    return {
        loading,
        data,
        dataList,
        total,
        pageIndex,
        pageSize,
        pageCount,
        filters,
        runAsync,
        run,
        cancel,
    }
}