package com.ga.common.util;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.LocalDate;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class DateUtilTest {

    @Test
    @DisplayName("getMonthRange: 평월")
    void monthRange_normal() {
        String[] r = DateUtil.getMonthRange("202605");
        assertThat(r).containsExactly("2026-05-01", "2026-05-31");
    }

    @Test
    @DisplayName("getMonthRange: 윤년 2월")
    void monthRange_leap() {
        String[] r = DateUtil.getMonthRange("202402");
        assertThat(r).containsExactly("2024-02-01", "2024-02-29");
    }

    @Test
    @DisplayName("getMonthRange: 평년 2월")
    void monthRange_normalFeb() {
        String[] r = DateUtil.getMonthRange("202302");
        assertThat(r).containsExactly("2023-02-01", "2023-02-28");
    }

    @Test
    @DisplayName("calcMonthDiff: yyyymm 문자열")
    void monthDiff_yyyymm() {
        assertThat(DateUtil.calcMonthDiff("202401", "202405")).isEqualTo(4);
        assertThat(DateUtil.calcMonthDiff("202312", "202401")).isEqualTo(1);
        assertThat(DateUtil.calcMonthDiff("202405", "202401")).isEqualTo(-4);
        assertThat(DateUtil.calcMonthDiff("202401", "202401")).isZero();
    }

    @Test
    @DisplayName("calcMonthDiff: LocalDate")
    void monthDiff_date() {
        // 같은 달의 다른 일자는 0개월
        assertThat(DateUtil.calcMonthDiff(LocalDate.of(2024, 1, 1), LocalDate.of(2024, 1, 31))).isZero();
        assertThat(DateUtil.calcMonthDiff(LocalDate.of(2024, 1, 31), LocalDate.of(2024, 2, 1))).isEqualTo(1);
        assertThat(DateUtil.calcMonthDiff(LocalDate.of(2023, 1, 1), LocalDate.of(2024, 1, 1))).isEqualTo(12);
    }

    @Test
    @DisplayName("addMonth: 월 가산/연도 넘김")
    void addMonth() {
        assertThat(DateUtil.addMonth("202401", 3)).isEqualTo("202404");
        assertThat(DateUtil.addMonth("202312", 1)).isEqualTo("202401");
        assertThat(DateUtil.addMonth("202403", -3)).isEqualTo("202312");
    }

    @Test
    @DisplayName("parseDate: 패턴 일치/실패")
    void parseDate() {
        assertThat(DateUtil.parseDate("2026-05-10", "yyyy-MM-dd")).isEqualTo(LocalDate.of(2026, 5, 10));
        assertThat(DateUtil.parseDate("20260510", "yyyyMMdd")).isEqualTo(LocalDate.of(2026, 5, 10));
        assertThat(DateUtil.parseDate(null, "yyyy-MM-dd")).isNull();
        assertThat(DateUtil.parseDate("", "yyyy-MM-dd")).isNull();
        assertThat(DateUtil.parseDate("invalid", "yyyy-MM-dd")).isNull();
    }

    @Test
    @DisplayName("format: 패턴 적용")
    void format() {
        LocalDate d = LocalDate.of(2026, 5, 10);
        assertThat(DateUtil.format(d, "yyyy-MM-dd")).isEqualTo("2026-05-10");
        assertThat(DateUtil.format(d, "yyyyMMdd")).isEqualTo("20260510");
        assertThat(DateUtil.format(null, "yyyy-MM-dd")).isNull();
    }

    @Test
    @DisplayName("getMonthRange: 잘못된 yyyymm 은 예외")
    void monthRange_invalid() {
        assertThatThrownBy(() -> DateUtil.getMonthRange("2026"))
                .isInstanceOf(java.time.format.DateTimeParseException.class);
    }

    @Test
    @DisplayName("getSettleMonth(LocalDate): yyyyMM")
    void settleMonthOfDate() {
        assertThat(DateUtil.getSettleMonth(LocalDate.of(2026, 5, 10))).isEqualTo("202605");
        assertThat(DateUtil.getSettleMonth(LocalDate.of(2024, 12, 31))).isEqualTo("202412");
    }
}
