namespace Meezi.Core.Discover;

/// <summary>Opening hours for a single day.</summary>
public class DaySchedule
{
    public bool IsOpen { get; set; }
    /// <summary>24-h HH:mm, e.g. "08:00"</summary>
    public string? Open { get; set; }
    /// <summary>24-h HH:mm, e.g. "23:30". If past midnight, still next-calendar-day open time.</summary>
    public string? Close { get; set; }
}

/// <summary>
/// Full-week schedule. Iran week: Saturday = first day, Friday = last day.
/// Stored as JSON on <see cref="Entities.Cafe.WorkingHoursJson"/>.
/// </summary>
public class WorkingHoursSchedule
{
    public DaySchedule? Sat { get; set; }
    public DaySchedule? Sun { get; set; }
    public DaySchedule? Mon { get; set; }
    public DaySchedule? Tue { get; set; }
    public DaySchedule? Wed { get; set; }
    public DaySchedule? Thu { get; set; }
    public DaySchedule? Fri { get; set; }

    /// <summary>
    /// Returns the <see cref="DaySchedule"/> for the given UTC day-of-week,
    /// adjusted to Iran Standard Time (UTC+3:30).
    /// </summary>
    public DaySchedule? ForUtcNow()
    {
        // Iran Standard Time: UTC+03:30 (no DST)
        var iranOffset = TimeSpan.FromMinutes(210);
        var iranNow = DateTimeOffset.UtcNow.ToOffset(iranOffset);
        return iranNow.DayOfWeek switch
        {
            DayOfWeek.Saturday  => Sat,
            DayOfWeek.Sunday    => Sun,
            DayOfWeek.Monday    => Mon,
            DayOfWeek.Tuesday   => Tue,
            DayOfWeek.Wednesday => Wed,
            DayOfWeek.Thursday  => Thu,
            DayOfWeek.Friday    => Fri,
            _                   => null
        };
    }

    /// <summary>Returns true when the cafe is currently open based on Iran time.</summary>
    public bool IsOpenNow()
    {
        var day = ForUtcNow();
        if (day is null || !day.IsOpen) return false;
        if (string.IsNullOrEmpty(day.Open) || string.IsNullOrEmpty(day.Close)) return true; // open all day

        var iranOffset = TimeSpan.FromMinutes(210);
        var iranNow = DateTimeOffset.UtcNow.ToOffset(iranOffset);
        var nowMinutes = iranNow.Hour * 60 + iranNow.Minute;

        if (!TryParseMinutes(day.Open, out var openMin) || !TryParseMinutes(day.Close, out var closeMin))
            return true;

        // Handle spans crossing midnight (e.g. 22:00–02:00)
        if (closeMin <= openMin)
            return nowMinutes >= openMin || nowMinutes < closeMin;

        return nowMinutes >= openMin && nowMinutes < closeMin;
    }

    private static bool TryParseMinutes(string? hhmm, out int minutes)
    {
        minutes = 0;
        if (string.IsNullOrEmpty(hhmm)) return false;
        var parts = hhmm.Split(':');
        if (parts.Length != 2) return false;
        if (!int.TryParse(parts[0], out var h) || !int.TryParse(parts[1], out var m)) return false;
        minutes = h * 60 + m;
        return true;
    }
}
