package com.artfess.cqxy.utils;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.artfess.base.feign.UCFeignService;
import com.artfess.base.model.CommonResult;
import com.artfess.base.query.QueryField;
import com.artfess.base.query.QueryFilter;
import com.artfess.base.query.QueryOP;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.DateUtils;
import com.artfess.cqxy.projectManagement.dao.ProjectManagementDao;
import com.artfess.cqxy.projectManagement.manager.ProjectPersonnelManager;
import com.artfess.cqxy.universal.enums.FileTypeEnum;
import com.artfess.sysConfig.persistence.param.DictModel;
import com.artfess.uc.api.impl.util.ContextUtil;
import com.artfess.uc.api.model.IUser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.jsonwebtoken.lang.Collections;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xwpf.usermodel.ICell;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.security.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 业务工具类
 *
 * @author 黎沐华
 * @date 2022/2/24 11:45
 */
public class BizUtils {


    /**
     * 处理查询器通用过滤字段
     *
     * @param queryFilter 查询器
     * @param alias       主表别名
     * @param hasContract 是否和合同表有关联
     * @return 处理过的查询器
     */
    public static QueryFilter handleFilter(QueryFilter queryFilter, String alias, boolean hasContract) {
        queryFilter.addFilter(alias + ".IS_DELE_", "0", QueryOP.EQUAL);
        queryFilter.addFilter("pm.IS_DELE_", "0", QueryOP.EQUAL);
        queryFilter.addFilter("pm.VALID_FLAG_", 1, QueryOP.EQUAL);
        if (hasContract) {
            queryFilter.addFilter("bc.IS_DELE_", "0", QueryOP.EQUAL);
        }
        return queryFilter;
    }

    public static <T> List<T> list(List<T> list) {
        return null == list ? new ArrayList<T>() : list;
    }

    // 保留原有方法调用，避免过大改动
    public static QueryFilter handleFilter(QueryFilter queryFilter, String mAlias, String lAlias) {
        queryFilter.addFilter(mAlias + ".IS_DELE_", "0", QueryOP.EQUAL);
        queryFilter.addFilter(lAlias + ".IS_DELE_", "0", QueryOP.EQUAL);
        queryFilter.addFilter(lAlias + ".VALID_FLAG_", 1, QueryOP.EQUAL);
        return queryFilter;
    }

    /**
     * 由后缀名返回文件类型
     *
     * @param suffix
     * @return
     */
    public static Integer handleFileType(String suffix) {
        if ("bmp,jpg,jpeg,png,gif,webp".indexOf(suffix) != -1) {
            return Integer.valueOf(FileTypeEnum.one.getCode());
        }
        if ("docx,doc,xls,xlsx,ppt,pptx,pdf,htl,html,txt".indexOf(suffix) != -1) {
            return Integer.valueOf(FileTypeEnum.two.getCode());
        }
        if ("rar,zip,7z,gz,bz,ace,uha,uda,zpaq".indexOf(suffix) != -1) {
            return Integer.valueOf(FileTypeEnum.three.getCode());
        }
        if ("avi,wmv,mpg,mpeg,mov,rm,ram,swf,flv,mp4".indexOf(suffix) != -1) {
            return Integer.valueOf(FileTypeEnum.four.getCode());
        } else {
            return Integer.valueOf(FileTypeEnum.five.getCode());
        }
    }

    /**
     * 将字符串的首字母转大写
     *
     * @param str 需要转换的字符串
     * @return
     */
    public static String captureName(String str) {
        // 进行字母的ascii编码前移，效率要高于截取字符串进行转换的操作
        char[] cs = str.toCharArray();
        cs[0] -= 32;
        return String.valueOf(cs);
    }

    public static String handleDateFormat(Date date) {
        return null == date ? "" : new SimpleDateFormat("yyyy-MM-dd").format(date);
    }

    public static String dateFormatChineseStyle(Date date) {
        return null == date ? "" : new SimpleDateFormat("yyyy年MM月dd日").format(date);
    }

    public static String handleStringFormat(String str) {
        if (org.apache.commons.lang3.StringUtils.isBlank(str)) {
            return "";
        }
        return str;
    }

    /**
     * 处理单元格
     *
     * @param workbook  工作蒲
     * @param sheetName Sheet名，获取对应Sheet以设置行高列宽
     * @param cell      单元格
     * @param value     填入单元格中的值
     * @param title     是否是标题
     */
    public static void handelCell(HSSFWorkbook workbook, String sheetName, HSSFCell cell, String value, boolean... title) {
        //单元格设置值
        cell.setCellValue(StringUtils.isEmpty(value) ? " " : value);
        //创建样式
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        //设置水平居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        //设置垂直居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        //设置字体
        HSSFFont font = workbook.createFont();
        font.setFontName("宋体");//设置字体名称
        font.setFontHeightInPoints((short) 12);//设置字号
        if (title.length == 1 && title[0]) {
            font.setFontHeightInPoints((short) 14);
            font.setBold(true);//设置是否加粗
        }
        font.setColor(IndexedColors.BLACK.index);//设置字体颜色
        cellStyle.setFont(font);
        //自动换行
        cellStyle.setWrapText(true);
        //渲染单元格
        cell.setCellStyle(cellStyle);
        //列宽自适应、设置行高
        HSSFSheet sheet = workbook.getSheet(sheetName);
        sheet.setColumnWidth(0, 6 * 256);
        // 解决自动设置列宽中文失效的问题
//        sheet.setColumnWidth(cell.getColumnIndex(), sheet.getColumnWidth(cell.getColumnIndex()) * 9 / 10);
        int colWidth = sheet.getColumnWidth(cell.getColumnIndex()) * 2;
        sheet.autoSizeColumn(cell.getColumnIndex());
        if (colWidth < 255 * 256) {
            sheet.setColumnWidth(cell.getColumnIndex(), colWidth < 3000 ? 3000 : colWidth);
        } else {
            sheet.setColumnWidth(cell.getColumnIndex(), 6000);
        }
        sheet.getRow(cell.getRowIndex()).setHeightInPoints(30);
    }

    /**
     * 处理单元格 解决Style数量过多问题
     *
     * @param workbook  工作蒲
     * @param sheetName Sheet名，获取对应Sheet以设置行高列宽
     * @param cell      单元格
     * @param value     填入单元格中的值
     * @param title     是否是标题
     */
    public static void handelCell(HSSFWorkbook workbook, HSSFCellStyle cellStyle, String sheetName, HSSFCell cell, String value, boolean... title) {
        //单元格设置值
        cell.setCellValue(StringUtils.isEmpty(value) ? " " : value);
        //设置水平居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        //设置垂直居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        //设置字体
        HSSFFont font = workbook.createFont();
        font.setFontName("宋体");//设置字体名称
        font.setFontHeightInPoints((short) 12);//设置字号
        if (title.length == 1 && title[0]) {
            font.setFontHeightInPoints((short) 14);
            font.setBold(true);//设置是否加粗
        }
        font.setColor(IndexedColors.BLACK.index);//设置字体颜色
        cellStyle.setFont(font);
        //自动换行
        cellStyle.setWrapText(true);
        //渲染单元格
        cell.setCellStyle(cellStyle);
        //列宽自适应、设置行高
        HSSFSheet sheet = workbook.getSheet(sheetName);
        sheet.setColumnWidth(0, 6 * 256);
        // 解决自动设置列宽中文失效的问题
//        sheet.setColumnWidth(cell.getColumnIndex(), sheet.getColumnWidth(cell.getColumnIndex()) * 9 / 10);
        int colWidth = sheet.getColumnWidth(cell.getColumnIndex()) * 2;
        sheet.autoSizeColumn(cell.getColumnIndex());
        if (colWidth < 255 * 256) {
            sheet.setColumnWidth(cell.getColumnIndex(), colWidth < 3000 ? 3000 : colWidth);
        } else {
            sheet.setColumnWidth(cell.getColumnIndex(), 6000);
        }
        sheet.getRow(cell.getRowIndex()).setHeightInPoints(30);
    }

    /**
     * 处理单元格 解决Style数量过多问题
     *
     * @param workbook  工作蒲
     * @param sheetName Sheet名，获取对应Sheet以设置行高列宽
     * @param cell      单元格
     * @param value     填入单元格中的值
     * @param title     是否是标题
     */
    public static void handelCell(HSSFWorkbook workbook, HSSFCellStyle cellStyle, HSSFFont font, String sheetName, HSSFCell cell, String value, boolean... title) {
        //单元格设置值
        cell.setCellValue(StringUtils.isEmpty(value) ? " " : value);
        //设置水平居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        //设置垂直居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        //设置字体
//        HSSFFont font = workbook.createFont();
        font.setFontName("宋体");//设置字体名称
        font.setFontHeightInPoints((short) 12);//设置字号
        if (title.length == 1 && title[0]) {
            font.setFontHeightInPoints((short) 14);
            font.setBold(true);//设置是否加粗
        }
        font.setColor(IndexedColors.BLACK.index);//设置字体颜色
        cellStyle.setFont(font);
        //自动换行
        cellStyle.setWrapText(true);
        //渲染单元格
        cell.setCellStyle(cellStyle);
        //列宽自适应、设置行高
        HSSFSheet sheet = workbook.getSheet(sheetName);
        sheet.setColumnWidth(0, 6 * 256);
        // 解决自动设置列宽中文失效的问题
//        sheet.setColumnWidth(cell.getColumnIndex(), sheet.getColumnWidth(cell.getColumnIndex()) * 9 / 10);
        int colWidth = sheet.getColumnWidth(cell.getColumnIndex()) * 2;
        sheet.autoSizeColumn(cell.getColumnIndex());
        if (colWidth < 255 * 256) {
            sheet.setColumnWidth(cell.getColumnIndex(), colWidth < 3000 ? 3000 : colWidth);
        } else {
            sheet.setColumnWidth(cell.getColumnIndex(), 6000);
        }
        sheet.getRow(cell.getRowIndex()).setHeightInPoints(30);
    }

    /**
     * 将金额转换为大写
     *
     * @param v
     * @return
     */
    public static String changeMoney(double v) {
        final String UNIT = "万千佰拾亿千佰拾万千佰拾元角分";
        final String DIGIT = "零壹贰叁肆伍陆柒捌玖";
        final double MAX_VALUE = 9999999999999.99D;
        if (v < 0 || v > MAX_VALUE) {
            return "参数非法!";
        }
        long l = Math.round(v * 100);
        if (l == 0) {
            return "零元整";
        }
        String strValue = l + "";
        // i用来控制数
        int i = 0;
        // j用来控制单位
        int j = UNIT.length() - strValue.length();
        String rs = "";
        boolean isZero = false;
        for (; i < strValue.length(); i++, j++) {
            char ch = strValue.charAt(i);
            if (ch == '0') {
                isZero = true;
                if (UNIT.charAt(j) == '亿' || UNIT.charAt(j) == '万' || UNIT.charAt(j) == '元') {
                    rs = rs + UNIT.charAt(j);
                    isZero = false;
                }
            } else {
                if (isZero) {
                    rs = rs + "零";
                    isZero = false;
                }
                rs = rs + DIGIT.charAt(ch - '0') + UNIT.charAt(j);
            }
        }
        if (!rs.endsWith("分")) {
            rs = rs + "整";
        }
        rs = rs.replaceAll("亿万", "亿");
        return rs;
    }

    /**
     * 根据字典值获取字典文本
     *
     * @param dic  字典集合
     * @param code 值
     * @return 文本
     */
    public static String getDicValueByCode(List<DictModel> dic, String code) {
        if (Collections.isEmpty(dic)) {
            return "";
        }
        for (DictModel ele : dic) {
            if (ele.getValue().equals(code)) {
                return ele.getName();
            }
        }
        return "";
    }

    // 重载以兼容数值型的code
    public static String getDicValueByCode(List<DictModel> dic, Integer code) {
        return getDicValueByCode(dic, String.valueOf(code));
    }

    /**
     * 从字典中获取对应值的code
     *
     * @param dic   字典
     * @param value 值
     * @return
     */
    public static String getDicCodeByValue(List<DictModel> dic, String value) {
        if (Collections.isEmpty(dic)) {
            return "";
        }
        for (DictModel ele : dic) {
            if (ele.getName().equals(value)) {
                return ele.getValue();
            }
        }
        return "";
    }

    // 重载以兼容数值型的code
    public static Integer getDicCodeByValue_Int(List<DictModel> dic, String value) {
        if (Collections.isEmpty(dic)) {
            return null;
        }
        for (DictModel ele : dic) {
            if (ele.getName().equals(value)) {
                return Integer.valueOf(ele.getValue());
            }
        }
        return null;
    }

    public static String getDicCodeByValue_String(List<DictModel> dic, String value) {
        if (Collections.isEmpty(dic)) {
            return "";
        }
        for (DictModel ele : dic) {
            if (ele.getName().equals(value)) {
                return String.valueOf(ele.getValue());
            }
        }
        return null;
    }

    /**
     * 将数字翻译为英文单词
     *
     * @param value 数字
     * @return 英文单词
     */
    public static String convertNumber(String value) {
        switch (value) {
            case "1":
                return "one";
            case "2":
                return "two";
            case "3":
                return "three";
            case "4":
                return "four";
            case "5":
                return "five";
            case "6":
                return "six";
            case "7":
                return "seven";
            case "8":
                return "eight";
            case "9":
                return "nine";
            case "10":
                return "ten";
            case "11":
                return "eleven";
            case "12":
                return "twelve";
            case "13":
                return "thirteen";
            case "14":
                return "fourteen";
            case "15":
                return "fifteen";
            default:
                return value;
        }
    }

    // 重载以兼容数值型的数值
    public static String convertNumber(Integer value) {
        return convertNumber(String.valueOf(value));
    }

    /**
     * 将数字翻译为汉字
     *
     * @param value 数字
     * @return 汉字
     */
    public static String converttoChinaNumber(String value) {
        switch (value) {
            case "1":
                return "一";
            case "2":
                return "二";
            case "3":
                return "三";
            case "4":
                return "四";
            case "5":
                return "五";
            case "6":
                return "六";
            case "7":
                return "七";
            case "8":
                return "八";
            case "9":
                return "九";
            case "10":
                return "十";
            case "11":
                return "十一";
            case "12":
                return "十二";
            case "13":
                return "十三";
            case "14":
                return "十四";
            case "15":
                return "十五";
            default:
                return "";
        }
    }

    // 重载以兼容数值型的数值
    public static String converttoChinaNumber(Integer value) {
        return converttoChinaNumber(String.valueOf(value));
    }

    /**
     * 设置EasyPOI导出参数
     *
     * @param fileName 文件名
     * @return 导出参数
     */
    public static ExportParams getExportParams(String fileName) {
        ExportParams exportParams = new ExportParams(null, fileName);
        exportParams.setStyle(EasyPoiStyle.class);
        exportParams.setType(ExcelType.XSSF);
        return exportParams;
    }

    //赋默认值
    public static void setDefaultValue(Object object) {
        final String defaultStr = "";
        final Date defaultDate = new Date();
        final BigDecimal defaultDecimal = new BigDecimal(0);
        try {
            Class clazz = object.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                String fieldName = field.getName();
                Class fieldClass = field.getType();
                field.setAccessible(true); //设置访问权限
                if (isFieldValueNull(fieldName, object)) {
                    if (fieldClass == Integer.class) {
                        field.set(object, defaultDecimal.intValue());
                    } else if (fieldClass == Long.class) {
                        field.set(object, defaultDecimal.longValue());
                    } else if (fieldClass == Float.class) {
                        field.set(object, defaultDecimal.doubleValue());
                    } else if (fieldClass == BigDecimal.class) {
                        field.set(object, defaultDecimal);
                    } else if (fieldClass == Date.class) {
                        field.set(object, defaultDate);
                    } else if (fieldClass == String.class) {
                        field.set(object, defaultStr); // 设置值
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }

    //判断字段是否为空
    private static boolean isFieldValueNull(String fieldName, Object object) throws ClassNotFoundException {
        boolean isNUll = false;
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = object.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(object, new Object[]{});
            if (value == null || "null".equals(String.valueOf(value))) {
                isNUll = true;
            }
            return isNUll;
        } catch (Exception e) {
            return isNUll;
        }
    }

    public static String getYearByQueryFields(List<QueryField> queryFields) throws Exception {
        String year = null;
        for (QueryField ele : queryFields) {
            if ("COMMENCEMENT_TIME_".equalsIgnoreCase(ele.getProperty())) {
                if (null != ele.getValue() && ele.getValue() instanceof Date) {
                    year = new SimpleDateFormat("yyyy").format(DateUtils.parseDate(ele.getValue().toString(), "yyyy-MM-dd"));
//                    year = String.valueOf(((Date) ele.getValue()).getYear());
                }
                if (null != ele.getValue() && ele.getValue() instanceof List) {
                    List value = (List) ele.getValue();
                    if (null != value && value.size() > 0) {
                        year = new SimpleDateFormat("yyyy").format(DateUtils.parseDate(value.get(0).toString(), "yyyy-MM-dd"));
                    }
                }
                break;
            }
            if (null == year) {
                if ("CREATE_TIME_".equalsIgnoreCase(ele.getProperty())) {
                    if (null != ele.getValue() && ele.getValue() instanceof Date) {
                        year = String.valueOf(((LocalDateTime) ele.getValue()).getYear());
                    }
                    break;
                }
            }
        }

        return year;
    }

    public static Boolean isProjectIdFields(List<QueryField> queryFields) {
        for (QueryField ele : queryFields) {
            if ("pm.ID_".equalsIgnoreCase(ele.getProperty()) || ele.getProperty().toUpperCase().indexOf("PROJECT_ID_") > 0) {
                return false;
            }
        }
        return true;
    }


    public static List<String> handProjectAuthByUser(UCFeignService ucFeignService,
                                                     ProjectPersonnelManager projectPersonnelManager,
                                                     ProjectManagementDao projectManagementDao) {
        //查询项目时通过项目人员增加查询条件，只有管理员或者可以管理此项目的人员才能查询到此项目
        IUser user = ContextUtil.getCurrentUser();
        // 如果是管理员或者没有项目权限
        if (null != user) {
//            String currentUserId = baseContext.getCurrentUserId();
            boolean disableAll = false;
            Integer userType = user.getUserType();
            String userId = user.getUserId();
            CommonResult<JsonNode> userNode = ucFeignService.getUserById(userId);
            if (userNode.getState()) {
                JsonNode userJsonNode = userNode.getValue();
                if (null != userJsonNode) {
                    userType = userJsonNode.get("userType").asInt();
                }
            }
            // 1.先通过用户类型判断，过滤掉超级管理员之类的用户
            if (userType != null && userType != 0 && userType != 1) {
                // 2.再通过角色判断，过滤掉没有对应角色权限的人员
                // 获取当前用户拥有的所有角色
                Set<String> set = new HashSet<String>();
                List<ObjectNode> list = ucFeignService.getRoleListByAccount(user.getAccount());
                if (BeanUtils.isNotEmpty(list)) {
                    for (ObjectNode objectNode : list) {
                        set.add(objectNode.get("code").asText());
                    }
                }
                if (!set.contains("sysRole") && !set.contains("bld") && !set.contains("xmgl")) {
                    disableAll = true;
                }
            }
            if (disableAll) {
                List<String> projectIds = projectPersonnelManager.getProjectByPersonnelId(userId);
                List<String> projectIdsByuserIdList = projectManagementDao.queryProjectIdsByUserId(userId);
                if (null == projectIds) {
                    projectIds = new ArrayList<>();
                }
                projectIds.addAll(projectIdsByuserIdList);
                // 去重
                List projectIdList = (List) projectIds.stream().distinct().collect(Collectors.toList());
                return projectIdList;
            }
        }
        return null;
    }

    public static void removeSame(List<Map<String, Object>> list) {
        for (int i = 0; i < list.size() - 1; i++) {
            for (int j = list.size() - 1; j > i; j--) {
                if (list.get(j).get("tableName").equals(list.get(i).get("tableName"))) {
                    list.remove(j);
                }
            }
        }
    }

    public static String getCellValue(Cell cell) {
        String cellValue = "";
        // 以下是判断数据的类型
        switch (cell.getCellTypeEnum()) {
            case NUMERIC: // 数字
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    cellValue = sdf.format(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(cell.getNumericCellValue())).toString();
                } else {
                    DataFormatter dataFormatter = new DataFormatter();
                    cellValue = dataFormatter.formatCellValue(cell);
                }
                break;
            case STRING: // 字符串
                cellValue = cell.getStringCellValue();
                break;
            case BOOLEAN: // Boolean
                cellValue = cell.getBooleanCellValue() + "";
                break;
            case FORMULA: // 公式
                cellValue = cell.getCellFormula() + "";
                break;
            case BLANK: // 空值
                cellValue = "";
                break;
            case ERROR: // 故障
                cellValue = "非法字符";
                break;
            default:
                cellValue = "未知类型";
                break;
        }
        return cellValue;
    }

}