package com.bonus.common.core.utils;

import org.junit.Test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoField;
import java.util.Date;
import java.util.List;

import static org.junit.Assert.*;

public class DateUtilsTest {

    @Test
    public void testGetNowDate() {
        assertNotNull(DateUtils.getNowDate());
    }

    @Test
    public void testGetDate() {
        String date = DateUtils.getDate();
        assertNotNull(date);
        assertEquals(new SimpleDateFormat("yyyy-MM-dd").format(new Date()), date);
    }

    @Test
    public void testGetTime() {
        String time = DateUtils.getTime();
        assertNotNull(time);
        assertEquals(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), time);
    }

    @Test
    public void testParseDate() {
        String dateStr = "2024-08-13";
        Date date = DateUtils.parseDate(dateStr);
        assertNotNull(date);
        assertEquals(dateStr, new SimpleDateFormat("yyyy-MM-dd").format(date));
    }

    @Test
    public void testDaysBetween() {
        String startDateStr = "2023-12-31";
        Date startDate = DateUtils.parseDate(startDateStr);
        Date futureDate = DateUtils.addDays(startDate, 60);
        long daysBetween = DateUtils.daysBetween(startDate, futureDate);
        assertEquals(60, daysBetween);
    }

    @Test
    public void testDaysBetweenCrossYear() throws ParseException {
        String startDateStr = "2023-12-31";
        String endDateStr = "2024-01-02";
        Date startDate = DateUtils.parseDate(startDateStr);
        Date endDate = DateUtils.parseDate(endDateStr);
        long daysBetween = DateUtils.daysBetween(startDate, endDate);
        assertEquals(2, daysBetween);
    }

    @Test
    public void testAddDays() {
        Date now = new Date();
        Date futureDate = DateUtils.addDays(now, 5);
        assertNotNull(futureDate);

        Date pastDate = DateUtils.addDays(now, -5);
        assertNotNull(pastDate);
    }

    @Test
    public void testAddDaysCrossMonth() throws ParseException {
        String dateStr = "2024-02-28";
        Date date = DateUtils.parseDate(dateStr);

        // 跨月测试，增加 1 天，应该得到 2024-03-01
        Date nextDay = DateUtils.addDays(date, 2);
        String nextDayStr = new SimpleDateFormat("yyyy-MM-dd").format(nextDay);
        assertEquals("2024-03-01", nextDayStr);
    }

    @Test
    public void testIsBefore() {
        Date now = new Date();
        Date futureDate = DateUtils.addDays(now, 5);
        assertTrue(DateUtils.isBefore(now, futureDate));
    }

    @Test
    public void testIsAfter() {
        Date now = new Date();
        Date pastDate = DateUtils.addDays(now, -5);
        assertTrue(DateUtils.isAfter(now, pastDate));
    }

    @Test
    public void testIsEqual() {
        Date now = new Date();
        Date sameDate = new Date(now.getTime());
        assertTrue(DateUtils.isEqual(now, sameDate));
    }

    @Test
    public void testGetUnixTimestamp() {
        long timestamp = DateUtils.getUnixTimestamp();
        assertTrue(timestamp > 0);
    }

    @Test
    public void testFromUnixTimestamp() {
        long timestamp = DateUtils.getUnixTimestamp();
        Date date = DateUtils.fromUnixTimestamp(timestamp);
        assertNotNull(date);
    }

    @Test
    public void testToUnixTimestamp() {
        Date date = new Date();
        long timestamp = DateUtils.toUnixTimestamp(date);
        assertTrue(timestamp > 0);
    }

    @Test
    public void testGetISO8601Timestamp() {
        String iso8601Timestamp = DateUtils.getISO8601Timestamp();
        assertNotNull(iso8601Timestamp);
    }

    @Test
    public void testFromISO8601Timestamp() {
        String iso8601Timestamp = DateUtils.getISO8601Timestamp();
        Date date = DateUtils.fromISO8601Timestamp(iso8601Timestamp);
        assertNotNull(date);
    }

    @Test
    public void testGetStartOfWeek() {
        Date startOfWeek = DateUtils.getStartOfWeek();
        assertNotNull(startOfWeek);

        // 检查是否为星期一
        LocalDate localDate = LocalDate.now();
        LocalDate expectedStart = localDate.with(java.time.DayOfWeek.MONDAY);
        assertEquals(DateUtils.toDate(expectedStart), startOfWeek);
    }

    @Test
    public void testGetEndOfWeek() {
        Date endOfWeek = DateUtils.getEndOfWeek();
        assertNotNull(endOfWeek);

        // 检查是否为星期日，并且时间为 23:59:59
        LocalDate localDate = LocalDate.now();
        LocalDateTime expectedEnd = localDate.with(java.time.DayOfWeek.SUNDAY).atTime(23, 59, 59);

        // 忽略毫秒部分进行比较
        LocalDateTime actualEnd = endOfWeek.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().withNano(0);
        assertEquals(expectedEnd, actualEnd);
    }

    @Test
    public void testGetWeekOfYear() {
        int weekOfYear = DateUtils.getWeekOfYear();
        assertEquals(LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR), weekOfYear);
    }

    @Test
    public void testGetDateBefore() {
        String dateStr = "2024-01-05";
        Date date = DateUtils.parseDate(dateStr);
        Date dateBefore = DateUtils.getDateBefore(date, 5);
        assertNotNull(dateBefore);
    }

    @Test
    public void testGetDateAfter() {
        String dateStr = "2024-12-31";
        Date date = DateUtils.parseDate(dateStr);
        Date dateAfter = DateUtils.getDateAfter(date, 5);
        assertNotNull(dateAfter);
    }

    @Test
    public void testGetMonthOrDay() {
        String monthOrDay = DateUtils.getMonthOrDay(28, "/");
        assertNotNull(monthOrDay);
        assertTrue(monthOrDay.matches("\\d{2}/\\d{2}"));
    }

    @Test
    public void testConvertToISO8601() {
        String dateStr = "2024-08-31 12:00:00";
        String iso8601 = DateUtils.convertToISO8601(dateStr, "yyyy-MM-dd HH:mm:ss");
        assertNotNull(iso8601);
        assertTrue(iso8601.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}"));
    }

    @Test
    public void testGetSecondsBetween() {
        String startTime = "2024-08-13 12:00:00";
        String endTime = "2024-08-13 12:01:00";
        long secondsBetween = DateUtils.getSecondsBetween(startTime, endTime, "yyyy-MM-dd HH:mm:ss");
        assertEquals(60, secondsBetween);
    }

    @Test
    public void testGetWeekStartAndEndDate() {
        String dateStr = "2024-08-13";
        String[] weekDates = DateUtils.getWeekStartAndEndDate(dateStr, "yyyy-MM-dd");
        assertNotNull(weekDates);
        assertEquals(2, weekDates.length);
        assertTrue(weekDates[0].matches("\\d{4}-\\d{2}-\\d{2}"));
        assertTrue(weekDates[1].matches("\\d{4}-\\d{2}-\\d{2}"));
    }

    @Test
    public void testGetWeekStartAndEndDateTime() {
        String dateStr = "2024-08-13";
        String[] weekDateTimes = DateUtils.getWeekStartAndEndDateTime(dateStr, "yyyy-MM-dd");
        assertNotNull(weekDateTimes);
        assertEquals(2, weekDateTimes.length);
        assertTrue(weekDateTimes[0].matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"));
        assertTrue(weekDateTimes[1].matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"));
    }

    @Test
    public void testGetWeekOfMonth() {
        String dateStr = "2024-08-13";
        int weekOfMonth = DateUtils.getWeekOfMonth(dateStr, "yyyy-MM-dd");
        assertTrue(weekOfMonth > 0);
    }

    @Test
    public void testGetCurrentYear() {
        String currentYear = DateUtils.getCurrentYear();
        assertEquals(String.valueOf(LocalDate.now().getYear()), currentYear);
    }

    @Test
    public void testGetCurrentMonth() {
        String currentMonth = DateUtils.getCurrentMonth();
        assertEquals(String.format("%02d", LocalDate.now().getMonthValue()), currentMonth);
    }

    @Test
    public void testGetCurrentDay() {
        String currentDay = DateUtils.getCurrentDay();
        assertEquals(String.format("%02d", LocalDate.now().getDayOfMonth()), currentDay);
    }

    @Test
    public void testDateTimeNow() {
        String dateTimeNow = DateUtils.dateTimeNow();
        assertNotNull(dateTimeNow);
        assertEquals(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()), dateTimeNow);
    }

    @Test
    public void testParseDateToStr() {
        Date now = new Date();
        String formattedDate = DateUtils.parseDateToStr("yyyy-MM-dd", now);
        assertEquals(new SimpleDateFormat("yyyy-MM-dd").format(now), formattedDate);
    }

    @Test
    public void testDateTime() {
        String dateString = "2024-08-13";
        Date date = DateUtils.dateTime("yyyy-MM-dd", dateString);
        assertNotNull(date);
        assertEquals(dateString, new SimpleDateFormat("yyyy-MM-dd").format(date));
    }

    @Test
    public void testTimeDistance() {
        Date now = new Date();
        Date later = DateUtils.addDays(now, 1);
        String distance = DateUtils.timeDistance(later, now, null);
        assertEquals("1天0小时0分钟", distance);
    }

    @Test
    public void testToDate() {
        LocalDateTime now = LocalDateTime.now();
        Date date = DateUtils.toDate(now);
        assertNotNull(date);
    }

    @Test
    public void testToLocalDateTime() {
        Date date = new Date();
        LocalDateTime localDateTime = DateUtils.toLocalDateTime(date);
        assertNotNull(localDateTime);
    }

    @Test
    public void testGetServerStartDate() {
        Date serverStartDate = DateUtils.getServerStartDate();
        assertNotNull(serverStartDate);
    }

    @Test
    public void testDatePath() {
        String datePath = DateUtils.datePath();
        assertNotNull(datePath);
        assertEquals(new SimpleDateFormat("yyyy/MM/dd").format(new Date()), datePath);
    }

    @Test
    public void testToLocalDate(){
        String dateString = "2024-08-13";
        Date date = DateUtils.dateTime("yyyy-MM-dd", dateString);
        LocalDate localDate = DateUtils.toLocalDate(date);
        assertNotNull(localDate);
    }


    @Test
    public void testToLocalTime(){
        String dateString = "2024-08-13 10:00:00";
        Date date = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString);
        LocalTime localTime = DateUtils.toLocalTime(date);
        assertNotNull(localTime);
    }


    @Test
    public void testDateTime2(){
        String s = DateUtils.dateTime();
        assertNotNull(s);
    }


    @Test
    public void testHoursBetween(){
        String dateString1 = "2024-08-13 10:00:00";
        Date date1 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString1);
        String dateString2 = "2024-08-13 11:00:00";
        Date date2 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString2);
        long l = DateUtils.hoursBetween(date1, date2);
        assertEquals(1L,l);
    }


    @Test
    public void testMinutesBetween(){
        String dateString1 = "2024-08-13 10:00:00";
        Date date1 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString1);
        String dateString2 = "2024-08-13 11:00:00";
        Date date2 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString2);
        long l = DateUtils.minutesBetween(date1, date2);
        assertEquals(60L,l);
    }


    @Test
    public void testAddHours(){
        String dateString1 = "2024-08-13 10:00:00";
        Date date1 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString1);
        String dateString2 = "2024-08-13 11:00:00";
        Date date2 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString2);
        Date date = DateUtils.addHours(date1, 1);
        assertEquals(date2,date);
    }


    @Test
    public void testAddMinutes(){
        String dateString1 = "2024-08-13 10:00:00";
        Date date1 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString1);
        String dateString2 = "2024-08-13 11:00:00";
        Date date2 = DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", dateString2);
        Date date = DateUtils.addMinutes(date1, 60);
        assertEquals(date2,date);
    }


    @Test
    public void testGetDatesBefore(){
        List<String> datesBefore = DateUtils.getDatesBefore(5, "yyyy-MM-dd");
        assertNotNull(datesBefore);
    }

    @Test
    public void testGetDatesAfter(){
        List<String> datesBefore = DateUtils.getDatesAfter(5, "yyyy-MM-dd");
        assertNotNull(datesBefore);
    }

    @Test
    public void testGetDatesAfter1(){
        List<String> datesBefore = DateUtils.getDatesAfter("2024-02-04",5, "yyyy-MM-dd");
        assertNotNull(datesBefore);
    }


    @Test
    public void testGetDatesBefore1(){
        List<String> datesBefore = DateUtils.getDatesBefore("2024-02-04",5, "yyyy-MM-dd");
        assertNotNull(datesBefore);
    }







}
