package com.qmth.exam.reserve.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.qmth.boot.core.exception.StatusException;

public class DateUtil {

    private static final Logger log = LoggerFactory.getLogger(DateUtil.class);

    public final static String LongDateString = "yyyy-MM-dd HH:mm:ss";
    public final static String LongZHDateString = "yyyy年MM月dd日 HH:mm:ss";
    public final static String LongZHNoSecondString = "yyyy年MM月dd日 HH:mm";
    public final static String ShortDateString = "yyyy-MM-dd";
    public final static String ShortDateStringWithoutSplit = "yyyyMMdd";
    public final static String ShortTimeString = "HH:mm:ss";
    public final static String ShortTimeStringWithoutSplit = "HHmmss";
    public final static String LongDateStringWithoutSplit = "yyyyMMddHHmmss";
    public final static String MillisecondDateString = "yyyyMMddHHmmssSSS";
    public final static String HourMinuteString = "HH:mm";

    private static Map<String, ThreadLocal<SimpleDateFormat>> SimpleDateForamtThreadLocalMap = new HashMap<String, ThreadLocal<SimpleDateFormat>>();

    static {
        // 初始化常见的日期类型
        synchronized (DateUtil.class) {
            SimpleDateForamtThreadLocalMap.put(ShortDateString, InitThreadLocal(ShortDateString));
            SimpleDateForamtThreadLocalMap.put(ShortDateStringWithoutSplit,
                    InitThreadLocal(ShortDateStringWithoutSplit));
            SimpleDateForamtThreadLocalMap.put(LongDateString, InitThreadLocal(LongDateString));
            SimpleDateForamtThreadLocalMap.put(LongDateStringWithoutSplit, InitThreadLocal(LongDateStringWithoutSplit));
            SimpleDateForamtThreadLocalMap.put(MillisecondDateString, InitThreadLocal(MillisecondDateString));
            SimpleDateForamtThreadLocalMap.put(ShortTimeString, InitThreadLocal(ShortTimeString));
            SimpleDateForamtThreadLocalMap.put(ShortTimeStringWithoutSplit,
                    InitThreadLocal(ShortTimeStringWithoutSplit));
        }
    }

    public static String getLongDateByLongTime(Long time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(LongDateString);
        Date date = new Date(time);
        return simpleDateFormat.format(date);
    }

    public static String getShortDateByLongTime(Long time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(ShortDateString);
        Date date = new Date(time);
        return simpleDateFormat.format(date);
    }

    public static String getShortDateWithoutSplitByLongTime(Long time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(ShortDateStringWithoutSplit);
        Date date = new Date(time);
        return simpleDateFormat.format(date);
    }

    public static Long getLongTimeByDate(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(LongDateString);
        try {
            Date date = sdf.parse(dateStr);
            Long timestamp = date.getTime();
            return timestamp;
        } catch (ParseException e) {
            log.error(e.getMessage());
            throw new StatusException("日期转换失败！");
        }
    }

    public static Long getLongTimeByZHDate(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(LongZHDateString);
        try {
            Date date = sdf.parse(dateStr);
            Long timestamp = date.getTime();
            return timestamp;
        } catch (ParseException e) {
            log.error(e.getMessage());
            throw new StatusException("日期转换失败！");
        }
    }

    public static void main(String[] args) {
        // String result = formatShortDateString(new Date());
        // System.out.println(result);
        // Date date = new Date(1715749200000l);
        // String result = format(date, "yyyy-MM-dd HH:mm:ss");
        // System.out.println(result);
        System.out.println(getLongDateByLongTime(1714093200000L));
    }

    public static Date addValues(int filed, int value) {
        return addValues(new Date(), filed, value);
    }

    public static Date addValues(Date date, int filed, int value) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(filed, value);
        return c.getTime();
    }

    public static String format(Date date, String pattern) {
        SimpleDateFormat sdf = getFormatter(pattern);
        try {
            return sdf.format(date);
        } catch (Exception e) {

        }
        return null;
    }

    public static String formatShortString(Date date, String pattern) {
        try {
            return getFormatter(pattern).format(date);
        } catch (Exception e) {
            return null;
        }
    }

    public static String formatShortDateString(Date date) {
        return formatShortString(date, ShortDateStringWithoutSplit);
    }

    public static String formatShortSplitDateString(Date date) {
        return formatShortString(date, ShortDateString);
    }

    public static Date parse(String source, String pattern) {
        if (StringUtils.isEmpty(pattern))
            pattern = LongDateString;
        if (StringUtils.isEmpty(source))
            return null;
        SimpleDateFormat sdf = getFormatter(pattern);
        try {
            return sdf.parse(source);
        } catch (Exception e) {

        }
        return null;
    }

    public static SimpleDateFormat getFormatter(final String pattern) {
        ThreadLocal<SimpleDateFormat> tl = SimpleDateForamtThreadLocalMap.get(pattern);
        if (tl == null) {
            synchronized (DateUtil.class) {
                if (tl == null) {
                    tl = SimpleDateForamtThreadLocalMap.get(pattern);
                    if (tl == null)
                        SimpleDateForamtThreadLocalMap.put(pattern, InitThreadLocal(pattern));
                }
            }
            tl = SimpleDateForamtThreadLocalMap.get(pattern);
        }
        return tl.get();
    }

    public static boolean isBetwwen(Date start, Date end) {
        return isBetwwen(new Date(), start, end);
    }

    public static boolean isBetwwen(Date now, Date start, Date end) {
        if (now.after(start) && now.before(end))
            return true;
        else
            return false;
    }

    public static ThreadLocal<SimpleDateFormat> InitThreadLocal(final String pattern) {
        ThreadLocal<SimpleDateFormat> sdf = new ThreadLocal<SimpleDateFormat>() {
            @Override
            protected SimpleDateFormat initialValue() {
                return new SimpleDateFormat(pattern);
            }
        };
        return sdf;
    }

    /**
     * 获取某天的起点时间
     *
     * @param date
     *            某个日期
     * @param changeDays
     *            日期前后调整几天
     * @return 示例：2024-01-01 00:00:00
     */
    public static Date changeDateAndTimeBegin(Date date, int changeDays) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, changeDays);

        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取某天的终点时间
     *
     * @param date
     *            某个日期
     * @param changeDays
     *            日期前后调整几天
     * @return 示例：2024-01-01 23:59:59
     */
    public static Date changeDateAndTimeEnd(Date date, int changeDays) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, changeDays);

        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    public static String getStartAndEndTime(long startTime, long endTime) {
        try {
            Date start = new Date(startTime);
            Date end = new Date(endTime);
            return format(start, LongZHNoSecondString) + "-" + format(end, HourMinuteString);
        } catch (Exception e) {
            throw new StatusException("日期转化异常");
        }
    }

}
