import {message, Select, Tooltip} from 'antd';
import { history } from "@umijs/max";
import { stringify } from "querystring";
import React, { useEffect, useRef } from 'react'
import style from '@/global.less';
import datadictionary from "@/utils/dataDictionary";

const { Option } = Select;
/**
 *
 * @param obj
 * @returns {string}
 */
export const getValue = obj =>
    Object.keys(obj)
        .map(key => obj[key])
        .join(",");

/**
 * 获取用户信息
 * @type {*}
 */
export let userInfo = getUserInfo();

export function setUserInfo() {
    userInfo = getUserInfo();
}

/**
 * 获取用户信息
 * @returns {any}
 */
export function getUserInfo() {
    if (isJSON(localStorage.getItem("antd-token-user"))) {
        return JSON.parse(localStorage.getItem("antd-token-user"));
    } else {
        replaceGoto();
    }
}

/**
 * 获取用户权限信息
 * @returns {any}
 */
export function getUserAuthority() {
    if (isJSON(localStorage.getItem("antd-pro-authority"))) {
        return JSON.parse(localStorage.getItem("antd-pro-authority"));
    } else {
        replaceGoto();
    }
}

/**
 * 获取用户Token信息
 * @returns {string|string}
 */
export function getTokenAuthority() {
    return localStorage.getItem("antd-token-authority");
}

/**
 * 获取用户所有按钮权限信息
 * @returns {string|string}
 */
export function getButtonAuthorityAll() {
    let buttonAuth = localStorage.getItem('antd-pro-button')
    return '' !== buttonAuth && buttonAuth ? JSON.parse(buttonAuth) : {}
}

/**
 * 验证用户按钮权限信息
 * @returns {boolean}
 */
export function checkButtonAuthority(key) {
    if(!key) return true

    try {
        let buttonObject = {}
        let pathName = window.location.pathname
        const buttonAuth = localStorage.getItem('antd-pro-button')
        if ('' !== buttonAuth && buttonAuth) {
            const button = JSON.parse(buttonAuth) ?? {}
            buttonObject = button[pathName] ?? {}
        }

        return buttonObject[key] !== undefined ? buttonObject[key] : true
    } catch {
        return true
    }
}

/**
 * 跳到登录页面
 */
function replaceGoto() {
    if (window.location.pathname !== "/login") {
        const redirect = window.location.pathname === "/" || window.location.pathname === "/welcome" ? {} : { redirect: window.location.href };
        if (localStorage.getItem("antd-token-authority")) {
            message.config({ maxCount: 1 })
            message.error("用户信息获取失败，请重新登陆")

            history.replace({
                pathname: "/login",
                search: stringify(redirect)
            })

            localStorage.clear()
        }
    }
}

/**
 * 货币格式化
 * @param value
 * @returns {string}
 */
export const formatNumber = (value) => {
    let oldNumber;
    let newNumber;
    let intNumber;
    let decimalNumber;
    if (value !== undefined) {
        value += "";
        if (value.indexOf(".") !== -1) {
            oldNumber = value.split(".");
            intNumber = (parseInt(oldNumber[0]).toLocaleString()).toString();
            decimalNumber = oldNumber[1].toString();
            newNumber = "￥" + intNumber + "." + decimalNumber;
            return newNumber;
        } else {
            oldNumber = value;
            intNumber = (parseInt(oldNumber).toLocaleString()).toString();
            newNumber = "￥" + intNumber;
            return newNumber;
        }
    }
};

/**
 * 去掉数组对象中的重复对象
 * @param obj
 * @returns {[]}
 */
export function deleteObject(obj) {
    let uniques = [];
    let stringify = {};
    for (let i = 0; i < obj.length; i++) {
        const keys = Object.keys(obj[i]);
        keys.sort(function(a, b) {
            return (Number(a) - Number(b));
        });
        let str = "";
        for (let j = 0; j < keys.length; j++) {
            str += JSON.stringify(keys[j]);
            str += JSON.stringify(obj[i][keys[j]]);
        }
        if (!stringify.hasOwnProperty(str)) {
            uniques.push(obj[i]);
            stringify[str] = true;
        }
    }
    return uniques;
}


/**
 * 金额小写转大写
 * @param amount
 * @returns {string}
 */
export function amountLtoU(amount) {
    if (isNaN(amount) || amount >= 1000000000000) return "无效金额！";  //数值最大不超过1万亿
    let sPrefix = amount < 0 ? "(负)" : "";                             //将负号‘-’显示成汉字‘(负)’
    let sAmount = Math.abs(amount).toFixed(2);                          //格式化成两位小数格式（两位小数对应“'角”和“分”）
    let sUnit = "仟佰拾亿仟佰拾万仟佰拾元角分";                         //14个权位单位
    let sCapital = "零壹贰叁肆伍陆柒捌玖";                              //10个大写数字
    sAmount = sAmount.replace(".", "");                                 //去除小数点（使数字与权位对应）
    sUnit = sUnit.substr(sUnit.length - sAmount.length);                //截取权位
    let sOutput = "";
    for (let i = 0, len = sAmount.length; i < len; i++) {               //拼接数字与权位单位
        sOutput += sCapital.substr(sAmount.substr(i, 1), 1) + sUnit.substr(i, 1);
    }
    return sPrefix + sOutput.replace(/零角零分$/, "整").replace(/零[仟佰拾]/g, "零").replace(/零{2,}/g, "零")
        .replace(/零([亿|万])/g, "$1").replace(/零+元/, "元").replace(/亿零{0,3}万/, "亿").replace(/^元/, "零元");
}

/**
 * 验证字符串是否能转为json格式
 * @param str
 * @returns {boolean}
 */
export function isJSON(str) {
    if (typeof str == "string" && str != "{}") {
        try {
            const obj = JSON.parse(str);
            if (typeof obj == "object" && obj) {
                return true;
            } else {
                return false;
            }
        } catch (e) {
            // console.log('error：' + str + '!!!' + e);
            return false;
        }
    }
    // console.log('It is not a string!')
    return false;
}

/**
 * 银行卡号Luhn校验算法
 *
 * luhn校验规则：16位银行卡号（19位通用）:
 * 1.将未带校验位的 15（或18）位卡号从右依次编号 1 到 15（18），位于奇数位号上的数字乘以 2。
 * 2.将奇位乘积的个十位全部相加，再加上所有偶数位上的数字。
 * 3.将加法和加上校验位能被 10 整除。
 *
 * @param bankno 为银行卡号
 * @returns {boolean}
 */
function luhnCheck(bankno) {
    let lastNum = bankno.substr(bankno.length - 1, 1);//取出最后一位（与luhn进行比较）

    let first15Num = bankno.substr(0, bankno.length - 1);//前15或18位
    let newArr = new Array();
    for (let i = first15Num.length - 1; i > -1; i--) {    //前15或18位倒序存进数组
        newArr.push(first15Num.substr(i, 1));
    }
    let arrJiShu = new Array();  //奇数位*2的积 <9
    let arrJiShu2 = new Array(); //奇数位*2的积 >9

    let arrOuShu = new Array();  //偶数位数组
    for (let j = 0; j < newArr.length; j++) {
        if ((j + 1) % 2 == 1) {//奇数位
            if (parseInt(newArr[j]) * 2 < 9)
                arrJiShu.push(parseInt(newArr[j]) * 2);
            else
                arrJiShu2.push(parseInt(newArr[j]) * 2);
        } else //偶数位
            arrOuShu.push(newArr[j]);
    }

    let jishu_child1 = new Array();//奇数位*2 >9 的分割之后的数组个位数
    let jishu_child2 = new Array();//奇数位*2 >9 的分割之后的数组十位数
    for (let h = 0; h < arrJiShu2.length; h++) {
        jishu_child1.push(parseInt(arrJiShu2[h]) % 10);
        jishu_child2.push(parseInt(arrJiShu2[h]) / 10);
    }

    let sumJiShu = 0; //奇数位*2 < 9 的数组之和
    let sumOuShu = 0; //偶数位数组之和
    let sumJiShuChild1 = 0; //奇数位*2 >9 的分割之后的数组个位数之和
    let sumJiShuChild2 = 0; //奇数位*2 >9 的分割之后的数组十位数之和
    let sumTotal = 0;
    for (let m = 0; m < arrJiShu.length; m++) {
        sumJiShu = sumJiShu + parseInt(arrJiShu[m]);
    }

    for (let n = 0; n < arrOuShu.length; n++) {
        sumOuShu = sumOuShu + parseInt(arrOuShu[n]);
    }

    for (let p = 0; p < jishu_child1.length; p++) {
        sumJiShuChild1 = sumJiShuChild1 + parseInt(jishu_child1[p]);
        sumJiShuChild2 = sumJiShuChild2 + parseInt(jishu_child2[p]);
    }
    //计算总和
    sumTotal = parseInt(sumJiShu) + parseInt(sumOuShu) + parseInt(sumJiShuChild1) + parseInt(sumJiShuChild2);

    //计算luhn值
    let k = parseInt(sumTotal) % 10 == 0 ? 10 : parseInt(sumTotal) % 10;
    let luhn = 10 - k;

    if (lastNum == luhn) {
        // console.log("验证通过");
        return true;
    } else {
        // message.error('银行卡号必须符合luhn校验')
        return false;
    }
}

/**
 * 非表单检查银行卡号
 * @param bankno
 * @returns {boolean}
 * @constructor
 */
export function CheckBankNo(bankno) {
    if (bankno == "" || bankno == undefined) {
        // message.error('请填写银行卡号')
        return false;
    }
    bankno = bankno.replace(/\s/g, "");
    if (bankno.length < 16 || bankno.length > 19) {
        // message.error('银行卡号长度必须在16到19之间')
        return false;
    }
    let num = /^\d*$/;//全数字
    if (!num.exec(bankno)) {
        // message.error('银行卡号必须全为数字')
        return false;
    }
    //开头6位
    let strBin = "10,18,30,35,37,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,60,62,65,68,69,84,87,88,94,95,98,99";
    if (strBin.indexOf(bankno.substring(0, 2)) == -1) {
        message.error("银行卡号开头6位不符合规范");
        return false;
    }
    //Luhn校验
    if (!luhnCheck(bankno)) {
        return false;
    }
    return true;
}

/**
 * 表单检查银行卡号
 * @param bankno
 * @returns {Promise<void>}
 * @constructor
 */
export function verifyBankNo(_, bankno) {
    if (bankno == "" || bankno == undefined) {
        return Promise.resolve();
    }
    bankno = bankno.replace(/\s/g, "");
    if (bankno.length < 16 || bankno.length > 19) {
        return Promise.reject("长度须在16到19之间");
    }
    let num = /^\d*$/;//全数字
    if (!num.exec(bankno)) {
        return Promise.reject("卡号须为数字");
    }
    //开头6位
    let strBin = "10,18,30,35,37,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,60,62,65,68,69,84,87,88,94,95,98,99";
    if (strBin.indexOf(bankno.substring(0, 2)) == -1) {
        return Promise.reject("开头6位不符合规范");
    }
    //Luhn校验
    if (!luhnCheck(bankno)) {
        return Promise.reject("不合法");
    }
    return Promise.resolve();
}

/**
 * 表单正则表达式校验手机号
 * @param rule
 * @param value
 * @param callback
 */
export function verifyPhone(_, value) {
    //校验手机号，号段主要有(不包括上网卡)：130~139、150~153，155~159，180~189、166~168, 170~173、176~178。14号段为上网卡专属号段
    let regs = /^((13[0-9])|(16[6-8])|(17[0-3,6-8])|(15[^4,\\D])|(18[0-9])|(19[0-9]))\d{8}$/;
    if (value == undefined || value.length == 0) {
        return Promise.resolve();
    } else {
        let phone = value?.replace(/\s/g, "");//去除空格
        if (!regs.test(phone)) {
            return Promise.reject("不合法");
            //原提示信息过长不适合展示
        } else {
            return Promise.resolve();
        }
    }
}

/**
 * 非表单正则表达式校验手机号
 * @param value
 * @returns {boolean}
 */
export function validatePhone(value) {
    //校验手机号，号段主要有(不包括上网卡)：130~139、150~153，155~159，180~189、170~171、176~178。14号段为上网卡专属号段
    let regs = /^((13[0-9])|(17[0-1,6-8])|(15[^4,\\D])|(18[0-9]))\d{8}$/;
    if (value == undefined || value.length == 0) {
        return true;
    } else {
        let phone = value.replace(/\s/g, "");//去除空格
        if (!regs.test(phone)) {
            return false;
        } else {
            return true;
        }
    }
}

/**
 * 表单正则表达式校验URL
 * @param rule
 * @param value
 */
export function verifyUrl(_, value) {
    let strRegex = "^((https|http|ftp|rtsp|mms)?://)"
        + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" //ftp的user@
        + "(([0-9]{1,3}.){3}[0-9]{1,3}" // IP形式的URL- 199.194.52.184
        + "|" // 允许IP和DOMAIN（域名）
        + "([0-9a-z_!~*'()-]+.)*" // 域名- www.
        + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]." // 二级域名
        + "[a-z]{2,6})" // first level domain- .com or .museum
        + "(:[0-9]{1,4})?" // 端口- :80
        + "((/?)|" // a slash isn't required if there is no file name
        + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
    let re = new RegExp(strRegex);

    if (value == undefined || value.length == 0) {
        return Promise.resolve();
    } else {
        let url = value?.replace(/\s/g, "");//去除空格
        if (!re.test(url)) {
            return Promise.reject("不合法");
        } else {
            return Promise.resolve();
        }
    }
}

export function printHtml(idvalue) {
    window.document.body.innerHTML = window.document.getElementById(idvalue).innerHTML;
    window.print();
    window.location.reload();
}

/**
 * 表单校验上传文件列表
 * @param value
 * @returns {boolean}
 */
export function verifyUploadList(_, value) {
    if (value?.list?.length > 0) {
        return Promise.resolve();
    }
    if (_.required === false) {
        return Promise.resolve();
    }

    return Promise.reject("请上传附件");
}

// 去掉数组对象中的重复对象
export function deteleObject(obj) {
    let uniques = [];
    let stringify = {};
    for (let i = 0; i < obj.length; i++) {
        const keys = Object.keys(obj[i]);
        keys.sort(function(a, b) {
            return (Number(a) - Number(b));
        });
        let str = "";
        for (let j = 0; j < keys.length; j++) {
            str += JSON.stringify(keys[j]);
            str += JSON.stringify(obj[i][keys[j]]);
        }
        if (!stringify.hasOwnProperty(str)) {
            uniques.push(obj[i]);
            stringify[str] = true;
        }
    }
    uniques = uniques;
    return uniques;
}

/**
 * 通过value 取 key
 */
export function findKey (data, value, compare = (a, b) => a === b) {
    return Object.keys(data).find(k => compare(data[k], value.trim()))
}

// 数据合并
export function mergeRecursive(source, target) {
    for (var p in target) {
        try {
            if (target[p].constructor == Object) {
                source[p] = mergeRecursive(source[p], target[p]);
            } else {
                source[p] = target[p];
            }
        } catch (e) {
            source[p] = target[p];
        }
    }
    return source;
};

/**
 * 初始化下拉框选项
 * @param value
 */
export function handleSelect(value) {
    const children = [];
    Object.keys(value).forEach(function (key) {
        children.push(<Option key={key} style={{textAlign: 'center'}}>{value[key]}</Option>);
    });

    return children
}

/**
 * 初始化树下拉框选项
 * @param arr
 * @param val
 */
export function initTreeSelect(arr, val) {
    let title = ''
    if (arr?.length > 0) {
        function queryDictName(item, value) {
            for (let i = 0; i < item.length; i++) {
                if (item[i].value == value) {
                    title = item[i].title;
                    break
                } else if (item[i].children?.length > 0) {
                    queryDictName(item[i].children, value);
                }
            }
        }

        queryDictName(arr, val);
        return title
    }

    return val
}

/**
 * 格式化字典数据
 * @param val 字典值
 * @param label 文本对应key
 * @param value 值对应key
 * @returns {Array}
 */
export function formatDictOptions (val, label, value) {
    const type = Object.prototype.toString.call(val)
    let newArr = []

    if (type === '[object Object]') {
        Object.keys(val).map((item, index) => {
            newArr.push({
                label: val[item],
                value: item,
                key: index
            })
        })
    }

    if (type === '[object Array]') {
        val.map((item, index) => {
            newArr.push({
                label: item[label],
                value: item[value],
                key: index
            })
        })
    }

    return newArr
}

/**
 * 格式化字典数据
 * @param val 字典值
 * @param label 文本对应key
 * @param value 值对应key
 * @returns {Array}
 */
export function formatDictText (val, text, label, value) {
    const type = Object.prototype.toString.call(val)
    let newArr = ''

    if (type === '[object Object]') {
        Object.keys(val).map((item, index) => {
            if(item === text) {
                newArr = val[item]
                return;
            }
        })
    }

    if (type === '[object Array]') {
        val.map((item, index) => {
            if(item[value] === text) {
                newArr = item[label]
                return;
            }
        })
    }

    return newArr
}

/**
 * hooks组件挂载状态校验
 * @returns {Object}
 */
export function useUnmounted() {
    const mountedRef = useRef(false)

    useEffect(() => {
        mountedRef.current = true
        return () => {
            mountedRef.current = false
        }
    })

    return mountedRef
}

/**
 * 格式化文本ToolTip
 * @param text 文本值
 * @param width 文本宽度
 * @returns {JSX.Element}
 */
export function formatTooltipContent(text, width) {
    return '' !== text && ![null, undefined].includes(text) ? (
        <Tooltip title={text}>
            <span className={style.nowrapper} style={{width: `${width ?? 150}px`}}>
                {text}
            </span>
        </Tooltip>
    ) : (
        <></>
    );
}
