#nullable enable
using System.Globalization;
using Baya.Application.Models.Booking;

namespace Baya.Application.Features.Bookings;

/// <summary>
/// Maps the role-agnostic booking projection to the wire DTO. Money crosses as strings of IRR-Rial digits.
/// <paramref name="includeAddress"/> is the disclosure switch: the owning customer (and admin) receive the
/// decrypted address snapshot; the nurse view omits it (a booking's coarse location suffices for the nurse,
/// the full address is surfaced only through EVV/session flows). Care-instruction clinical fields are never
/// part of this DTO.
/// </summary>
internal static class BookingMapper
{
    public static BookingDetailDto ToDetailDto(BookingDetailProjection p, bool includeAddress)
        => new(
            p.Id,
            p.BookingRequestId,
            p.Status,
            p.NurseId,
            p.NurseName,
            p.PatientId,
            p.PatientName,
            p.VariantId,
            p.VariantSnapshotJson,
            p.CustomerAddressId,
            includeAddress ? p.AddressSnapshotJson : null,
            Money(p.GrossPriceIrr),
            Money(p.BalinyaarCommissionIrr),
            p.PlatformFeeRate,
            Money(p.NursePayoutAmount),
            p.PspFeeAmount is { } psp ? Money(psp) : null,
            p.SessionCount,
            p.ScheduledDate,
            p.ScheduledTimeStart,
            p.ScheduledTimeEnd,
            p.ConfirmedAt,
            p.CompletedAt,
            p.CancelledAt,
            p.CancelledBy,
            p.CancellationReason,
            p.CancellationPolicyCode,
            p.CancellationRefundPercentage,
            p.RefundableAmountIrr is { } refund ? Money(refund) : null,
            p.DisputeWindowEndsAt,
            p.CreatedAt,
            p.Sessions.Select(ToSessionSummary).ToList());

    private static BookingSessionSummaryDto ToSessionSummary(BookingSessionProjection s)
        => new(
            s.Id,
            s.SessionIndex,
            s.ScheduledDate,
            s.ScheduledTimeStart,
            s.ScheduledTimeEnd,
            s.Status,
            Money(s.VisitPayoutAmount),
            s.PayoutEligibleAt,
            s.EvvStatus ?? Domain.Entities.Booking.VisitVerificationStatus.Pending,
            s.CheckInAt,
            s.CheckOutAt,
            s.CheckInAddressMatch);

    private static string Money(long irr) => irr.ToString(CultureInfo.InvariantCulture);
}
