using System.Linq;
using FluentAssertions;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Calendar;
using Xunit;

namespace Wino.Core.Tests;

public class CalendarRangeTextFormatterTests
{
    private static readonly CalendarRangeTextFormatter Formatter = new();
    private static readonly TestDateContextProvider DateContextProvider = new("en-US", new DateOnly(2026, 3, 24));

    [Fact]
    public void Format_ReturnsMonthDay_ForSingleDate()
    {
        var range = CreateRange(
            CalendarDisplayType.Day,
            anchorDate: new DateOnly(2026, 3, 6),
            startDate: new DateOnly(2026, 3, 6),
            endDate: new DateOnly(2026, 3, 6));

        Formatter.Format(range, DateContextProvider).Should().Be("March 6");
    }

    [Fact]
    public void Format_ReturnsFullRange_ForDatesInSameMonth()
    {
        var range = CreateRange(
            CalendarDisplayType.Week,
            anchorDate: new DateOnly(2026, 3, 6),
            startDate: new DateOnly(2026, 3, 3),
            endDate: new DateOnly(2026, 3, 10));

        Formatter.Format(range, DateContextProvider).Should().Be("March 3 - 10");
    }

    [Fact]
    public void Format_ReturnsFullRange_ForDatesInDifferentMonths()
    {
        var range = CreateRange(
            CalendarDisplayType.Week,
            anchorDate: new DateOnly(2026, 4, 2),
            startDate: new DateOnly(2026, 3, 30),
            endDate: new DateOnly(2026, 4, 7));

        Formatter.Format(range, DateContextProvider).Should().Be("March 30 - April 7");
    }

    [Fact]
    public void Format_ReturnsAnchorMonth_WhenVisibleRangeSpansMonthGrid()
    {
        var range = CreateRange(
            CalendarDisplayType.Month,
            anchorDate: new DateOnly(2026, 3, 12),
            startDate: new DateOnly(2026, 2, 23),
            endDate: new DateOnly(2026, 4, 5));

        Formatter.Format(range, DateContextProvider).Should().Be("March 2026");
    }

    [Fact]
    public void Format_ReturnsAnchorMonth_WhenVisibleRangeHasExactlyTwentyEightDays()
    {
        var range = CreateRange(
            CalendarDisplayType.Month,
            anchorDate: new DateOnly(2026, 2, 14),
            startDate: new DateOnly(2026, 2, 1),
            endDate: new DateOnly(2026, 2, 28));

        Formatter.Format(range, DateContextProvider).Should().Be("February 2026");
    }

    private static VisibleDateRange CreateRange(
        CalendarDisplayType displayType,
        DateOnly anchorDate,
        DateOnly startDate,
        DateOnly endDate)
    {
        var dayCount = endDate.DayNumber - startDate.DayNumber + 1;
        var dates = Enumerable.Range(0, dayCount)
                              .Select(offset => startDate.AddDays(offset))
                              .ToArray();

        return new VisibleDateRange(
            displayType,
            anchorDate,
            startDate,
            endDate,
            anchorDate,
            dayCount,
            ContainsToday: false,
            SpansSingleMonth: startDate.Month == endDate.Month && startDate.Year == endDate.Year,
            Dates: dates);
    }

    private sealed class TestDateContextProvider(string cultureName, DateOnly today) : IDateContextProvider
    {
        public System.Globalization.CultureInfo Culture => System.Globalization.CultureInfo.GetCultureInfo(cultureName);
        public TimeZoneInfo TimeZone => TimeZoneInfo.Utc;
        public DateOnly GetToday() => today;
    }
}
