import { ListIitem } from "@/api/base/BaseDataModel";
import { CustomerFeeProductObject } from "@/api/receivable/receivableModel";
// import { PartitionList } from "@/api/customerfee/CustomerFeeSetModel";
import { EexpenseType } from "@/components/FormulaList/types";
import { FeeApprovalStatus } from "@/type/BaseBusinessFeeseType";
import { BaseZoning } from "@/type/BaseZoningAction";
import { isBoolean } from "lodash";
import { cloneDeep } from "./cloneDeep";
import { isArray, isArrayLength, isNumber, isObject, isString } from "./is";

/**
 * 获取汇率版本名称
 */
export function getBillRateLabel(rateVersionId: number, listBillRate: ListIitem[]) {
    if (!rateVersionId && rateVersionId > 0) return
    const billRate = listBillRate.find(item => Number(item.value) === rateVersionId)
    return billRate?.label
}

/**
     * 
     * @param data 处理的数据
     * @param type 分区
     * @param field 分割的字符
     */
export function dealWithData(data: Recordable, type: string) {
    let dealArr = isArrayLength(data[0].zipCodeBelongAreaList) ? data[0].zipCodeBelongAreaList : data
    if (!dealArr) return;
    let str = "";
    // 深拷贝数据
    const newData = cloneDeep(dealArr);
    switch (type) {
        case BaseZoning.ZONING_PORT:
            // 并接口岸编号
            str = newData.map(item => item.portCode).join(',');
            break;
        case BaseZoning.ZONING_POSTAL_CODE:
            // 并接邮编显示
            const filterData = newData.filter(item => item.startZipCode && item.endZipCode)
            str = filterData.map(item => {
                const startZipCode = item.startZipCode || ''
                const endZipCode = item.endZipCode || ''
                return startZipCode + ',' + endZipCode
            }).join('|')
            break;
        default:
            break;
    }
    return str;
}

/**
 * 显示邮编分区的正则、地址字符串
 */
export function dealWithPostalCodeStr(data: Recordable, field: string) {
    let dealArr = isArrayLength(data[0].zipCodeBelongAreaList) ? data[0].zipCodeBelongAreaList : data
    if (!dealArr) return;
    let str = "";
    // 深拷贝数据
    const newData = cloneDeep(dealArr);
    str = newData.map(item => item[field]).filter(item => item).join('、');
    return str
}

/**
 * 处理口岸分区数据
 */
export function dealZipCodeBelongAreaList(portWithZipCodeList: Recordable[]) {
    if (isArray(portWithZipCodeList) && portWithZipCodeList.length === 0) return []

    const result = portWithZipCodeList.reduce((bicc: Recordable, item: Recordable) => {
        const existing = bicc.find(({ portCode }) => portCode === item.portCode)
        if (existing) {
            existing.zipCodeBelongAreaList.push({
                startZipCode: item.startZipCode,
                endZipCode: item.endZipCode,
                zipCodeRegex: item.zipCodeRegex,
                address: item.address
            });
        } else {
            bicc.push({
                portCode: item.portCode,
                haveZipCodeArea: true,
                zipCodeBelongAreaList: [
                    {
                        startZipCode: item.startZipCode,
                        endZipCode: item.endZipCode,
                        zipCodeRegex: item.zipCodeRegex,
                        address: item.address
                    }
                ]
            });
        }
        return bicc;
    }, []);

    return result
}

/**
 * 处理国家/地区分区数据
 * @param countryInfoList 需处理的分区数据 
 * @param isHaveZipCodeArea 是否有邮编
 */
export function dealCountryInfoList(countryInfoList: Recordable[]): Recordable[] {
    if (isArray(countryInfoList) && countryInfoList.length === 0) return []

    const result = countryInfoList.reduce((bicc, item) => {
        const countryInfoList_ = item.countryInfoList.map((zipCodeData) => ({
            countryId: item.countryId,
            haveZipCodeArea: isArrayLength(item.countryInfoList) ? true : false,
            ...zipCodeData
        }));
        const outputList = countryInfoList_.reduce((acc, curr) => {
            if (isArrayLength(curr.zipCodeBelongAreaList)) {
                return curr;
            } else {
                // 如果是第一个对象，直接返回
                if (!acc.countryId) {
                    return {
                        countryId: curr.countryId,
                        haveZipCodeArea: curr.haveZipCodeArea,
                        zipCodeBelongAreaList: [
                            {
                                startZipCode: curr?.startZipCode,
                                endZipCode: curr?.endZipCode,
                                zipCodeRegex: curr?.zipCodeRegex,
                                address: curr?.address,
                                address1: curr?.address1,
                            }
                        ]
                    };
                }
                if (acc.countryId === curr.countryId) {
                    acc.zipCodeBelongAreaList.push({
                        startZipCode: curr?.startZipCode,
                        endZipCode: curr?.endZipCode,
                        zipCodeRegex: curr?.zipCodeRegex,
                        address: curr?.address,
                        address1: curr?.address1,
                    });
                }
            }
            // 返回叠加后的对象
            return acc;
        }, {});
        console.log(outputList, ":输出转化的邮编列表信息");
        bicc.push({
            id: item.id,
            feeId: item.feeId,
            partitionType: item.partitionType,
            partitionName: item.partitionName,
            isPartition: item.isPartition,
            orderNumber: item.orderNumber,
            remark: item.remark,
            countryInfoList: Object.keys(outputList).length > 0 ? [outputList] : [{ countryId: item.countryId, haveZipCodeArea: false }]
        });
        return bicc;
    }, []) as Recordable[]
    return result as []
}

/**
 * 处理国家/地区列表/客户列表按字母分组
 * @param countryList 国家/地区列表
 */
export function dealCountryList(list: Recordable[]) {
    if (!isArray(list)) return []
    const country = list.reduce((acc, current) => {
        const key = current.code;
        if (!acc[key]) {
            acc[key] = [];
        }
        acc[key].push(current);
        return acc;
    }, {});

    return country
}

/**
 * 处理口岸邮编列表降级数据
 */
export function dealProtTargetTableList(arrData: Recordable[]) {
    const transformedData = arrData.reduce((acc, current) => {
        if (isArrayLength(current.zipCodeBelongAreaList)) {
            current.zipCodeBelongAreaList.forEach((zipCode) => {
                acc.push({
                    portCode: current?.portCode,
                    haveZipCodeArea: current?.haveZipCodeArea,
                    startZipCode: zipCode?.startZipCode,
                    endZipCode: zipCode?.endZipCode,
                    zipCodeRegex: zipCode?.zipCodeRegex,
                    address: zipCode?.address
                });
            });
        }
        return acc;
    }, []);
    return transformedData
}

/**
 * 处理字符串转为显示数组
 * @param countModel 需要格式化的公式符号
 * @param calculatorData 公式符号列表数据
 * @returns 
 */
export function dealStrCalculatorData(countModel: Recordable, calculatorData: Recordable): EexpenseType[] {
    if (!countModel.formula) return []
    // 获取的公式字符串
    const formula = countModel.formula
    // 字符串转数组
    const targetKeys = formula.match(/({\d+}|{\w+}|\{\*\}|\{\@\}|\{\&\}|\{\<\}|\{\<=\}|\{\?\}|\{\(\}|\{\)\}|\{\==\}|\{\>\}|\{\:\}|\{\$\}|\{\>=\}|\{\|\|}|\{\|\}|\{\.\}|\{\+\}|\{\-\}|\{\*\}|\{\/\})|\{\#\w+#\}|\d/g)
    // 合并多个数组
    const mergeArray = calculatorData && Object.values(calculatorData).reduce((pv, cr) => [...pv, ...cr], []) as Recordable[] || []
    // 找到对应属性并且合并成数组
    const targetList: Recordable[] = []
    for (const item of targetKeys) {
        const obj = mergeArray.find(ac => ac.key == item)
        if (obj) {
            targetList.push(obj)
        }
    }
    const choiceList = targetList.map(item => ({ key: item.key, value: item.value, active: item.active }))
    return choiceList
}

/**
 * 数组扁平化并且去重
 */
export function flatPartitionList(nestedArr: Recordable[]) {
    // 将嵌套数组展开成一个单一数组
    const flattenedArr = nestedArr.reduce((acc, arr) => {
        return acc.concat(arr);
    }, []);

    // 使用 reduce 和 Map 进行去重
    const uniqueArr = flattenedArr.reduce((acc, obj) => {
        // 检查 Map 中是否已经有该对象
        if (!acc.map.has(obj.id)) {
            acc.map.set(obj.id, obj);
            acc.arr.push(obj);
        }
        return acc;
    }, { arr: [], map: new Map() }).arr;
    return uniqueArr
}

/**
 * 查找对应的产品名称
 * @param productId 产品id编号
 * @param productList 产品列表
 * @returns 
 */
export function dealProductIdToName(productId: string, productList: ListIitem[]) {
    // console.log(productId, ":productId");
    if (!productId) return
    const findData = productList.find(item => item.value === productId)
    return findData ? findData.label : ''
}

/**
 * 匹配费用查询结果
 * @param resultCode 返回的code值
 */
export function dealQueryResultCodeText(resultCode: number) {
    if (!isNumber(resultCode)) return
    const resultCodeArr = new Map([
        [0, "成功"],
        [1, "无价格设置"],
        [2, "计费异常"]
    ])
    return resultCodeArr.get(resultCode)
}

/**
 * 分区编号转为对象并设置为0
 */
export function zoningToInitObject(strArr: string[]) {
    if (!isArrayLength(strArr)) return {}
    const result = strArr.reduce((ac, cr) => {
        ac[cr] = 0;
        return ac;
    }, {});
    return result
}
/**
 * 两个分区编号数据区不同值
 */
export function zoningToInitOnly(strArr: string[], strArr2: string[]) {
    if (!isArrayLength(strArr)) return strArr2
    const uniqueArr = [...new Set(strArr.concat(strArr2))]; // 合并数组并去重
    const diffArr = uniqueArr.filter(item => !strArr.includes(item) || !strArr2.includes(item)); // 查找不同的值
    return diffArr
}

/**
 * 按字母排序
 */
export function alphabeticalOrder(paramslist: Recordable[]) {
    const customerList = cloneDeep(paramslist)
    if (!isArrayLength(customerList)) return []
    // 排序
    const list = customerList.sort((a, b) => {
        if (a.code > b.code) {
            return 1;
        } else if (a.code < b.code) {
            return -1;
        } else {
            return 0;
        }
    })

    return list
}

/**
 * 清空对象属性
 */
export function dealEmptyObject(data: Recordable) {
    const cloneObject = cloneDeep(data)
    // 判断键值对清空数据
    const result = Object.keys(cloneObject).reduce((ac, key) => {
        // 判断属性值的类型
        if (Array.isArray(cloneObject[key])) {
            // 如果是数组，就新建空数组
            ac[key] = [];
        } else if (isNumber(cloneObject[key])) {
            ac[key] = cloneObject[key]
        } else {
            // 否则设置为undefined
            ac[key] = undefined;
        }
        return ac;
    }, {});
    return result
}

/**
 * 重置对象值
 * @param obj 目标对象
 * @returns 
 */
export function deal_ResetObject(obj) {
    const cloneObj = cloneDeep(obj)
    Object.keys(cloneObj).forEach((key) => {
        if (cloneObj.hasOwnProperty(key)) {
            if (Array.isArray(cloneObj[key])) {
                cloneObj[key] = [];
            } else if (isString(cloneObj[key])) {
                cloneObj[key] = '';
            } else if (isNumber(cloneObj[key])) {
                cloneObj[key] = -1;
            } else if (isBoolean(cloneObj[key])) {
                cloneObj[key] = false;
            }
            // else if (typeof obj[key] === 'object' && obj[key] !== null) {
            //     deal_ResetObject(obj[key]);
            // }
        }
    })
    return cloneObj
}

/**
 * 设置目标对象值
 * @param obj 
 */
export function deal_SetObjectData(targerObj: Recordable, sourceObj: Recordable) {
    const cloneTargerObj = cloneDeep(targerObj)
    Object.keys(cloneTargerObj).forEach((key) => {
        if (cloneTargerObj.hasOwnProperty(key)) {
            if (
                Array.isArray(sourceObj[key]) ||
                isString(sourceObj[key]) ||
                isNumber(sourceObj[key]) ||
                isBoolean(sourceObj[key]) ||
                isObject(sourceObj[key])
            ) {
                cloneTargerObj[key] = sourceObj[key];
            }
        }
    })
    return cloneTargerObj
}

/**
 * 查找对应的列表名称
 * @param val 键值value
 * @param list 列表
 * @returns 
 */
export function dealListIitemToName(val: string | number, list: ListIitem[]) {
    if (!val && !isArrayLength(list)) return
    const findData = list.find(item => item.value == val)
    return findData ? findData.label : ''
}

/**
 * 处理对应的化扁平化对象
 */
export function deal_flat_initFlattenObj<T extends any>(param, str) {
    const cloneParam = cloneDeep(param)
    if (cloneParam.hasOwnProperty(str)) {
        delete cloneParam[str]
    }
    const params = Object.keys(cloneParam).reduce((rc, key) => {
        if (key.startsWith(`${str}.`)) {
            const subKey = key.replace(`${str}.`, "");
            rc[str] = rc[str] || {};
            rc[str][subKey] = cloneParam[key];
        } else {
            rc[key] = cloneParam[key];
        }
        return rc;
    }, {}) as T
    return params
}

/**
 * 扁平化对象
 */
export function deal_flat_flattenObj(obj) {
    const stack: any[] = [];
    const result = {};
    Object.keys(obj).forEach((key) => {
        stack.push([key, obj[key]]);
    });
    while (stack.length > 0) {
        const [key, value] = stack.pop();
        if (typeof value === 'object' && value !== null) {
            Object.entries(value).forEach(([nestedKey, nestedValue]) => {
                stack.push([`${key}.${nestedKey}`, nestedValue]);
            });
        } else {
            result[key] = '';
        }
    }
    return result;
}

// {
//     destinationAddress: {
//         address: "11",
//         zipCode: "22",
//         countryCode: "33",
//         portCode: "44"
//     }
// }  
// 转
// {
//     "destinationAddress.portCode": "44",
//     "destinationAddress.countryCode": "33",
//     "destinationAddress.zipCode": "22",
//     "destinationAddress.address": "11"
// }
/**
 * 迭代的方式来优化扁平化对象的转换
 * 如：
 * 
 * @param obj 
 * @param prefix 
 * @returns 
 */
export function deal_flat_flattenObject(obj, prefix = '') {
    const flattened = {};
    const stack: Recordable = [];

    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            stack.push([key, obj[key], '']);
        }
    }

    while (stack.length > 0) {
        const [key, value, prefix] = stack.pop();

        if (typeof value === 'object' && value !== null) {
            for (let nestedKey in value) {
                if (value.hasOwnProperty(nestedKey)) {
                    stack.push([nestedKey, value[nestedKey], prefix + key + '.']);
                }
            }
        } else {
            flattened[prefix + key] = value;
        }
    }

    return flattened;
}

/**
 * 处理费用的日期版本
 * @param customerFeeList 
 */
export function deal_FeeDateVersionList(customerFeeList: CustomerFeeProductObject[]) {
    if (!isArrayLength(customerFeeList)) return []
    const newCustomerFeeList: Recordable[] = []
    const customerFeeLength = customerFeeList.length
    for (let index = 0; index < customerFeeLength; index++) {
        const customerFee = customerFeeList[index];
        if (customerFee) {
            newCustomerFeeList.push({
                ...customerFee,
                value: `${customerFee.beginDate}_${customerFee.endDate}`,
                label: `${customerFee.beginDate}_${customerFee.endDate}`
            })
        }
    }
    return newCustomerFeeList
}

/**
 * 判断两个对象里的属性值是否相同
 * @param obj1 对象1
 * @param obj2 对象2
 * @returns 
 */
export function deal_arePropertiesEqual(obj1, obj2) {
    // 获取对象的属性名称数组
    const props1 = Object.keys(obj1);
    const props2 = Object.keys(obj2);
    // 确保属性数量相同
    if (props1.length !== props2.length) {
        return false;
    }
    // 对比属性值
    for (let prop of props1) {
        if (obj1[prop] !== obj2[prop]) {
            return false; // 发现不相同的属性值，返回 false
        }
    }
    // 所有属性值均相同，返回 true
    return true;
}

/**
 * 判断对象中的属性值是否为空
 * @param obj 
 * @returns 
 */
export function deal_arePropertiesNotEmpty(obj: Recordable) {
    if (!isObject(obj)) return true
    const isNotEmpty = Object.values(obj).every(item => !item)
    return isNotEmpty
}

/**
 * 比较两个对象的属性数量是否相同
 * @param obj1 
 * @param obj2 
 * @returns 
 */
export function deal_compareObjects(obj1, obj2) {
    // 首先检查对象类型
    if (typeof obj1 !== typeof obj2) {
        return false;
    }
    // 如果是基本数据类型，直接比较值
    if (typeof obj1 != "object" || obj1 === null) {
        return obj1 == obj2;
    }
    // 检查属性数量是否相同
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);
    console.log(keys1);
    console.log(keys2);
    if (keys1.length !== keys2.length) {
        return false;
    }
    // 遍历所有属性
    for (let key of keys1) {
        // 递归比较属性值
        if (!deal_compareObjects(obj1[key], obj2[key])) {
            return false;
        }
    }
    // 如果所有属性值都相同，则对象相同
    return true;
}

/**
 * 获取审批状态tag
 * @param status 审批状态类型
 * @returns 
 */
export const deal_getFeeApprovalStatusTag = (status: number) => {
    switch (status) {
        case FeeApprovalStatus.NO_APPROVAL:
            return 'info'
        case FeeApprovalStatus.PENDING_APPROVAL:
            return 'info'
        case FeeApprovalStatus.APPROVAL_BY:
            return 'success'
        case FeeApprovalStatus.APPROVAL_FAILED:
            return 'danger'
        default:
            return 'info'
    }
}

/**
 * 根据字段处理成二级数组
 * @param originalArray 源数组
 * @param field 字段
 * @returns 
 */
export function deal_repeatedlyArray(originalArray: Recordable[], field: string, sort?: string) {
    if (!isArrayLength(originalArray) && !field) {
        console.error('originalArray：数组数据不能为空，field不能为空！');
        return []
    }
    // 使用 reduce 进行分组
    const resultArray = originalArray.reduce((accumulator, item) => {
        const type = item[field];
        // 如果 accumulator 中不存在以 type 为键的数组，则创建一个空数组
        if (!accumulator[type]) {
            accumulator[type] = [];
        }
        // 将当前对象放入对应 type 的数组中
        accumulator[type].push(item);
        return accumulator;
    }, {});
    if(sort) {
        // 排序
        Object.keys(resultArray).forEach(type => {
            resultArray[type].sort((a, b) => a[sort] - b[sort]);
        });
    }
    // 将 resultArray 中的值转为数组，得到最终结果
    const finalResult = Object.values(resultArray);
    finalResult.sort((a, b) => b[0][field] - a[0][field]);
    return finalResult
}

/**
 * 获取当前审批的人数
 * @param data 
 * @returns 
 */
export function getApprovalRecordIdCounts(data: Recordable[]) {
    if(!isArrayLength(data)) return 0
    // 使用 reduce 方法计算 approvalRecordId 的出现次数
    const approvalRecordIdCounts = data.reduce((acc, item) => {
        acc[item.approvalRecordId] = (acc[item.approvalRecordId] || 0) + 1;
        return acc;
    }, {});

    // 找到出现次数最多的 approvalRecordId
    const maxCount = Math.max(...Object.values(approvalRecordIdCounts));
    return maxCount
}

/**
 * 获取邮编区间正则
 * @param start 例如：005
 * @param end 例如：089
 * @returns 
 */
export function generateZipCodeRegexForRange(start: number | string, end: number | string) {
    // 将起始和结束值转换为字符串
    const startStr = String(start).padStart(3, "0");
    const endStr = String(end).padStart(3, "0");

    // 用于保存不同部分的正则片段
    const parts: string[] = [];

    // 分析起始和结束的数位
    const startHundreds = parseInt(startStr[0]);
    const startTens = parseInt(startStr[1]);
    const startOnes = parseInt(startStr[2]);

    const endHundreds = parseInt(endStr[0]);
    const endTens = parseInt(endStr[1]);
    const endOnes = parseInt(endStr[2]);

    // 生成百位的匹配
    if (startHundreds === endHundreds) {
      if (startTens === endTens) {
        parts.push(`${startHundreds}${startTens}[${startOnes}-${endOnes}]`);
      } else {
        parts.push(`${startHundreds}${startTens}[${startOnes}-9]`);
        for (let i = startTens + 1; i < endTens; i++) {
          parts.push(`${startHundreds}${i}\\d`);
        }
        parts.push(`${startHundreds}${endTens}[0-${endOnes}]`);
      }
    } else {
      parts.push(`${startHundreds}${startTens}[${startOnes}-9]`);
      for (let i = startTens + 1; i < 10; i++) {
        parts.push(`${startHundreds}${i}\\d`);
      }
      for (let i = startHundreds + 1; i < endHundreds; i++) {
        parts.push(`${i}\\d\\d`);
      }
      for (let i = 0; i < endTens; i++) {
        parts.push(`${endHundreds}${i}\\d`);
      }
      parts.push(`${endHundreds}${endTens}[0-${endOnes}]`);
    }

    // 将所有部分组合成最终的正则表达式
    const regexStr = parts.join("|");
    return new RegExp(`^(${regexStr})$`);
}