package cn.com.ty.lift.system.utils;

import cn.com.ty.lift.common.utils.PojoUtils;
import cn.com.ty.lift.common.utils.ProjectUtils;
import cn.com.ty.lift.system.constants.CommonConstants;
import cn.com.ty.lift.system.homepage.dao.dto.request.PlatformCalendarRequest;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author huangyuan
 * @date 2019-12-13
 * @description
 */
public class CommonUtil {


    /***
     * @description 通过request获取ip
     * @date 2019-12-10
     * @param request 请求对象
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * @param timeA  时间A
     * @param timeB  时间B
     * @param dValue 差值
     * @return true:差值在指定范围内 false:差值不在指定范围内
     * @description 判断时间A和B差值的绝对值是否在指定的之间差值内
     * @date 2019-12-18 14:10
     */
    public static boolean durationJudge(LocalDateTime timeA, LocalDateTime timeB, Long dValue) {
        Duration duration = Duration.between(timeA, timeB);
        long diffDay = duration.toDays();
        return diffDay < dValue;
    }

    /**
     * @param transTimeStr 给定时间
     * @param monthFormat  转化为的月份时间格式
     * @return Map 类型对应时间格式 monthBegin:表示月初时间 monthEnd:表示月末时间
     * @description
     */
    public static Map<String, String> getMonthDate(String transTimeStr, String monthFormat) {
        Map<String, String> dateTypeToDateValue = new HashMap<>();
        //将传递时间字符串转化为localDate类型时间
        LocalDate transDate = LocalDate.parse(transTimeStr, DateTimeFormatter.ofPattern(monthFormat));
        //设置月初时间
        LocalDate monthBeginDate = transDate.with(TemporalAdjusters.firstDayOfMonth());
        dateTypeToDateValue.put(CommonConstants.PlatformCalendarConstants.MONTH_BEGIN_DATE,
                monthBeginDate.format(DateTimeFormatter.ofPattern(monthFormat)));
        //设置月末时间
        LocalDate monthEndDate = transDate.with(TemporalAdjusters.lastDayOfMonth());
        dateTypeToDateValue.put(CommonConstants.PlatformCalendarConstants.MONTH_END_DATE,
                monthEndDate.format(DateTimeFormatter.ofPattern(monthFormat)));

        return dateTypeToDateValue;
    }

    /**
     * @param platformCalendarRequest 转化时间
     * @return
     * @description 设置月初月末时间
     */
    public static void setMonthDate(PlatformCalendarRequest platformCalendarRequest) {
        String dateStr = platformCalendarRequest.getRequestDateStr();
        //如果请求时间为空，就设置带天的请求时间
        if (StringUtils.isBlank(dateStr)) {
            dateStr = platformCalendarRequest.getRequestDateDayStr();
        }
        Map<String, String> dateTypeToDateValue = CommonUtil.getMonthDate(dateStr,
                CommonConstants.PlatformCalendarConstants.TRANS_DATE_FORMAT);
        //设置月初时间
        platformCalendarRequest.setMonthBeginStr(dateTypeToDateValue.get(
                CommonConstants.PlatformCalendarConstants.MONTH_BEGIN_DATE));
        //设置月末时间
        platformCalendarRequest.setMonthEndStr(dateTypeToDateValue.get(
                CommonConstants.PlatformCalendarConstants.MONTH_END_DATE));
    }

    /**
     * @param timeDateStr 传递时间
     * @param timeFormat  时间格式
     * @return
     * @description 初始化日列数据
     */
    public static Map<Integer, Map<Integer, Long>> initCalendarMapData(String timeDateStr, String timeFormat) {
        //将传递时间字符串转化为localDate类型时间
        LocalDate transDate = LocalDate.parse(timeDateStr, DateTimeFormatter.ofPattern(timeFormat));
        Map<Integer, Map<Integer, Long>> dayToLiftStatusToNum = new HashMap<>();
        if (transDate != null) {
            int dayNum = getLastDayNumOfMonth(transDate);
            for (int monthDay = 1; monthDay <= dayNum; monthDay++) {
                dayToLiftStatusToNum.put(monthDay, new HashMap<>());
            }
        }
        return dayToLiftStatusToNum;
    }

    /**
     * @param time 时间值
     * @return
     * @description 获取时间的天数值
     */
    public static int getDateDayValue(LocalDate time) {
        if (time != null) {
            return time.getDayOfMonth();
        }
        return 0;
    }

    /**
     * @param timeStr    时间值 - 字符串
     * @param timeFormat 时间格式
     * @return
     * @description 获取日期的天数值
     */
    public static int getDateStrDayValue(String timeStr, String timeFormat) {
        if (StringUtils.isNotBlank(timeStr)) {
            LocalDate time = LocalDate.parse(timeStr, DateTimeFormatter.ofPattern(timeFormat));
            return getDateDayValue(time);
        }
        return 0;
    }

    /**
     * @param dataList     数据集
     * @param dateAttrName 对应的属性名称，类型LocalDate
     * @return
     * @description 将数据转化为map 日期天 -> 数据集合
     */
    public static Map getKeyToDataModel(List dataList, String dateAttrName) {
        Map dayToDataModel = new HashMap();
        if (dataList != null && dataList.size() > 0) {
            dayToDataModel = (Map) dataList.stream().collect(Collectors.groupingBy(obj -> {
                try {
                    Method method = obj.getClass().getMethod(PojoUtils.attrGetMethodName(dateAttrName));
                    Object value = method.invoke(obj);
                    if (value != null) {
                        if (value instanceof LocalDate) {
                            return getDateDayValue((LocalDate) value);
                        }
                        return value;
                    }
                    return 0;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }));
        }
        return dayToDataModel;
    }

    /**
     * @param dataList     数据集合
     * @param dateAttrName 日期数据
     * @return
     * @description 将数据转化为map 天 -> 数据集合(数据集合 map: 电梯id -> 数据集合)
     */
    public static Map getDayToDataMap(List dataList, String dateAttrName) {
        Map dayToDataMap = new HashMap();
        //将数据转化为map 日期天 -> 数据集合
        Map dayToDataModel = getKeyToDataModel(dataList, dateAttrName);
        //将map集合转化为 liftId -> 数据集合
        dayToDataModel.forEach((dayValue, dataModelList) -> {
            dayToDataMap.put(dayValue, getKeyToDataModel((List) dataModelList, "liftId"));
        });
        return dayToDataMap;
    }

    /**
     * @param
     * @return
     * @description 获取某月的天数
     */
    public static int getLastDayNumOfMonth(LocalDate date) {
        if (date != null) {
            return date.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        }
        return 0;
    }

    /**
     * @param
     * @return
     * @description 获取给点日期字符串指定格式的月的天数
     * @date 2020/2/28 2:57 下午
     */
    public static int getLastDayNumOfMonthFromDateStr(String dateStr, String format) {
        if (StringUtils.isNotBlank(dateStr)) {
            LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(format));
            return getLastDayNumOfMonth(date);
        }
        return 0;
    }

}
