package com.yifu.cloud.plus.v1.yifu.insurances.util;

import cn.hutool.core.date.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * @author licancan
 * @description 日期工具类
 * @date 2022-07-19 14:20:54
 */
public class LocalDateUtil {
	/**
	 * 年格式：yyyy
	 */
	public static final String NORM_YEAR_PATTERN = "yyyy";
	/**
	 * 年月格式：yyyy-MM
	 */
	public static final String NORM_MONTH_PATTERN = "yyyy-MM";
	/**
	 * 标准日期格式：yyyy-MM-dd
	 */
	public static final String NORM_DATE_PATTERN = "yyyy-MM-dd";
	/**
	 * 标准时间格式：HH:mm:ss
	 */
	public static final String NORM_TIME_PATTERN = "HH:mm:ss";
	/**
	 * 标准日期时间格式，精确到分：yyyy-MM-dd HH:mm
	 */
	public static final String NORM_DATETIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm";
	/**
	 * 标准日期时间格式，精确到秒：yyyy-MM-dd HH:mm:ss
	 */
	public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

	/**
	 * 判断是否是日期
	 *
	 * @author licancan
	 * @param strDate
	 * @return {@link Boolean}
	 */
	public static Boolean isDate(String strDate,String pattern){
		if (Common.isEmpty(strDate)){
			return false;
		}
		try {
			DateFormat dateFormat = new SimpleDateFormat(pattern);
			Date date = dateFormat.parse(strDate);
			Calendar cal = Calendar.getInstance();
			cal.setTime(date);
			return true;
		}catch (ParseException pe){
			System.out.println("日期解析异常，返回false");
			return false;
		}
	}

	/**
	 * 字符串格式的日期转LocalDate
	 *
	 * @author licancan
	 * @param strDate
	 * @return {@link LocalDate}
	 */
	public static LocalDate parseLocalDate(String strDate){
		try {
			if (isDate(strDate,NORM_DATE_PATTERN)){
				DateFormat dateFormat = new SimpleDateFormat(NORM_DATE_PATTERN);
				Date date = dateFormat.parse(strDate);
				return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
			}
			return null;
		}catch (Exception e){
			System.out.println("字符串格式的日期转LocalDate失败");
			return null;
		}
	}

	/**
	 * 判断时间是否是将来时间（大于当天）
	 *
	 * @author licancan
	 * @param strDate
	 * @return {@link boolean}
	 */
	public static boolean isFutureDate(String strDate){
		boolean flag = false;
		//在日期字符串非空时执行
		if (!Common.isEmpty(strDate)) {
			//今日的开始时间
			Date nowDate = new Date();
			Date pastDate = null;
			//格式化日期
			SimpleDateFormat sdf = new SimpleDateFormat(NORM_DATE_PATTERN, Locale.CHINA);
			try {
				//将字符串转为日期格式，如果此处字符串为非合法日期就会抛出异常。
				pastDate = sdf.parse(strDate);
				//调用Date里面的after方法来做判断
				flag = pastDate.after(nowDate);
				if (flag) {
					System.out.println("该日期晚于今日");
				}else {
					System.out.println("该日期早于今日");
				}
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println("日期参数不可为空");
		}
		return flag;
	}

	/**
	 * 定时任务判断是否过期专用方法
	 *
	 * @author licancan
	 * @param strDate
	 * @return {@link boolean}
	 */
	public static boolean isOverdueDate(String strDate){
		boolean flag = false;
		//在日期字符串非空时执行
		if (!Common.isEmpty(strDate)) {
			//这里需要把传进来的日期加上23:59:59，来判断是否过期
			strDate = strDate + " 23:59:59";
			//今日的开始时间
			Date nowDate = new Date();
			Date pastDate = null;
			//格式化日期
			SimpleDateFormat sdf = new SimpleDateFormat(NORM_DATETIME_PATTERN, Locale.CHINA);
			try {
				//将字符串转为日期格式，如果此处字符串为非合法日期就会抛出异常。
				pastDate = sdf.parse(strDate);
				//调用Date里面的after方法来做判断
				flag = pastDate.after(nowDate);
				if (flag) {
					System.out.println("该日期晚于今日");
				}else {
					System.out.println("该日期早于今日");
				}
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println("日期参数不可为空");
		}
		return flag;
	}

	/**
	 * 比较两个时间的早晚
	 *
	 * @author licancan
	 * @param startDate 开始日期
	 * @param endDate 结束日期
	 * @return {@link boolean}
	 */
	public static boolean compareDate(String startDate,String endDate){
		boolean flag = false;
		//在日期字符串非空时执行
		if (!Common.isEmpty(startDate) && !Common.isEmpty(endDate)) {
			Date parseStartDate = null;
			Date parseEndDate = null;
			//格式化日期
			SimpleDateFormat sdf = new SimpleDateFormat(NORM_DATE_PATTERN, Locale.CHINA);
			try {
				//将字符串转为日期格式，如果此处字符串为非合法日期就会抛出异常。
				parseStartDate = sdf.parse(startDate);
				parseEndDate = sdf.parse(endDate);
				//调用Date里面的before方法来做判断
				flag = parseStartDate.before(parseEndDate);
				if (flag) {
					System.out.println("开始日期早于结束日期");
				}else {
					System.out.println("开始日期晚于结束日期");
				}
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println("日期参数不可为空");
		}
		return flag;
	}

	/**
	 * 判断传入的月份是否大于等于本月（结算月份 >= 派单月份）
	 *
	 * @author licancan
	 * @param strMonth 传入的月份
	 * @return {@link boolean}
	 */
	public static boolean isCurrentOrFutureMonth(String strMonth){
		boolean flag = false;
		//在日期字符串非空时执行
		if (!Common.isEmpty(strMonth)) {
			SimpleDateFormat sdf = new SimpleDateFormat(NORM_MONTH_PATTERN, Locale.CHINA);
			try {
				//当前时间
				Calendar cal1 = Calendar.getInstance();
				//传入的字符串解析时间
				Calendar cal2 = Calendar.getInstance();
				Date parseDate = sdf.parse(strMonth);
				cal2.setTime(parseDate);
				if (cal1 == null || cal2 == null) {
					throw new IllegalArgumentException("The date must not be null");
				}
				if (cal2.get(Calendar.YEAR) > cal1.get(Calendar.YEAR)){
					flag = true;
				}else if(cal2.get(Calendar.YEAR) == cal1.get(Calendar.YEAR) && cal2.get(Calendar.MONTH) >= cal1.get(Calendar.MONTH)){
					flag = true;
				}
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println("年月参数不可为空");
		}
		return flag;
	}

	/**
	 * 计算相差多少天,如果开始时间晚于结束时间会对调
	 *
	 * @author licancan
	 * @param startDate
	 * @param endDate
	 * @return {@link long}
	 */
	public static long betweenDay(String startDate,String endDate){
		long dif = 0;
		//在日期字符串非空时执行
		if (!Common.isEmpty(startDate) && !Common.isEmpty(endDate)) {
			Date parseStartDate = null;
			Date parseEndDate = null;
			//格式化日期
			SimpleDateFormat sdf = new SimpleDateFormat(NORM_DATE_PATTERN, Locale.CHINA);
			try {
				//将字符串转为日期格式，如果此处字符串为非合法日期就会抛出异常。
				parseStartDate = sdf.parse(startDate);
				parseEndDate = sdf.parse(endDate);
				//调用hutool里面的DateUtil.betweenDay方法来做判断
				dif = DateUtil.betweenDay(parseStartDate, parseEndDate, true);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println("日期参数不可为空");
		}
		return dif + 1;
	}

	/**
	 * 计算相差月份,如果开始时间晚于结束时间会对调
	 * 公式：(endYear - starYear) * 12 + endMonth - startMonth + (endDay >= startDay ? 1 : 0)
	 * @author licancan
	 * @param startDate
	 * @param endDate
	 * @return {@link long}
	 */
	public static long betweenMonth(String startDate,String endDate){
		long dif = 0;
		//在日期字符串非空时执行
		if (!Common.isEmpty(startDate) && !Common.isEmpty(endDate)) {
			Date parseStartDate = null;
			Date parseEndDate = null;
			//格式化日期
			SimpleDateFormat sdf = new SimpleDateFormat(NORM_DATE_PATTERN, Locale.CHINA);
			try {
				//将字符串转为日期格式，如果此处字符串为非合法日期就会抛出异常。
				parseStartDate = sdf.parse(startDate);
				parseEndDate = sdf.parse(endDate);

				//如果开始时间晚于结束时间对调
				if (parseStartDate.after(parseEndDate)) {
					Date t = parseStartDate;
					parseStartDate = parseEndDate;
					parseEndDate = t;
				}

				Calendar starCalendar = Calendar.getInstance();
				starCalendar.setTime(parseStartDate);
				Calendar endCalendar = Calendar.getInstance();
				endCalendar.setTime(parseEndDate);
				int starYear = starCalendar.get(Calendar.YEAR);
				int startMonth = starCalendar.get(Calendar.MONTH);
				int startDay = starCalendar.get(Calendar.DATE);
				int endYear = endCalendar.get(Calendar.YEAR);
				int endMonth = endCalendar.get(Calendar.MONTH);
				int endDay = endCalendar.get(Calendar.DATE);
				dif = (endYear - starYear) * 12 + endMonth - startMonth + (endDay >= startDay ? 1 : 0);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}else {
			System.out.println("日期参数不可为空");
		}
		return dif;
	}

	/**
	 * 判断两个时间段是否有交集
	 *
	 * 思路：将有交集的情况列出,若不符合有交集的情况,则无交集
	 *    有交集的两种情况
	 *    1.第一个时间段的开始时间在第二个时间段的开始时间和结束时间当中
	 *    2.第二个时间段的开始时间在第一个时间段的开始时间和结束时间当中
	 *
	 * @author licancan
	 * @param leftStartDate 第一个时间段的开始时间
	 * @param leftEndDate 第一个时间段的结束时间
	 * @param rightStartDate 第二个时间段的开始时间
	 * @param rightEndDate 第二个时间段的结束时间
	 * @return {@link boolean} 若有交集, 返回true, 否则返回false
	 */
	public static boolean hasOverlap(LocalDate leftStartDate, LocalDate leftEndDate, LocalDate rightStartDate, LocalDate rightEndDate) {
		return ((leftStartDate.equals(rightStartDate) || leftStartDate.isAfter(rightStartDate))
				&& leftStartDate.isBefore(rightEndDate))
				||
				(leftStartDate.isAfter(rightStartDate)
						&& (leftStartDate.equals(rightEndDate) || leftStartDate.isBefore(rightEndDate)))
				||
				((rightStartDate.equals(leftStartDate) || rightStartDate.isAfter(leftStartDate))
						&& rightStartDate.isBefore(leftEndDate))
				||
				(rightStartDate.isAfter(leftStartDate)
						&& (rightStartDate.equals(leftEndDate) || rightStartDate.isBefore(leftEndDate)));
	}

	public static void main(String[] args) {
		System.out.println(parseLocalDate("2022-8-3"));
	}
}
