using System;
using System.Collections.Generic;
using System.Linq;
using Baya.Domain.Entities.Booking;

namespace Baya.Application.Features.Bookings;

/// <summary>
/// Shared cancellation resolution + refund arithmetic for the whole-booking and single-session cancel paths.
/// The applicable policy is resolved by <c>(actor, lead-time bucket)</c>; only un-started (still
/// <c>scheduled</c>) sessions are refundable; the refund is a percentage of those sessions' share of gross.
/// </summary>
internal static class CancellationHelper
{
    public static string ResolveActor(bool isAdmin, bool isAssignedNurse)
        => isAdmin ? CancellationActor.Admin
            : isAssignedNurse ? CancellationActor.Nurse
            : CancellationActor.Customer;

    /// <summary>Hours from <paramref name="nowUtc"/> to the scheduled start (negative once it has started).</summary>
    public static double HoursBeforeStart(DateOnly date, TimeOnly start, DateTime nowUtc)
        => (date.ToDateTime(start, DateTimeKind.Utc) - nowUtc).TotalHours;

    public static CancellationPolicy ResolvePolicy(IReadOnlyList<CancellationPolicy> policies, double hoursBeforeStart)
        => policies.FirstOrDefault(p => p.Covers(hoursBeforeStart));

    /// <summary>The refundable amount (IRR) = <paramref name="refundPercentage"/> of the un-started sessions'
    /// share of gross, rounded half away from zero.</summary>
    public static long Refundable(long refundableGrossBase, decimal refundPercentage)
        => (long)decimal.Round(refundableGrossBase * refundPercentage / 100m, MidpointRounding.AwayFromZero);
}
