#nullable enable
using Baya.Application.Models.Booking;
using Baya.Application.Models.Common;
using Baya.Application.Models.Payments;
using Baya.Domain.Entities.Booking;

namespace Baya.Application.Contracts.Persistence;

/// <summary>
/// The post-payment <c>bookings</c> aggregate (bookings + sessions + care instructions + EVV). Writes load
/// tracked rows; reads project to role-scoped DTOs. Money is IRR <c>long</c> throughout; the encrypted
/// address snapshot and care fields decrypt only on the gated read paths. Tenancy is enforced in the
/// handlers from the ids these projections carry — a cross-party access is a clean not-found, never a leak.
/// </summary>
public interface IBookingRepository
{
    // ---- conversion ----
    Task AddAsync(Booking booking, CancellationToken cancellationToken);

    /// <summary>The booking id already created from this request, if any — the idempotency check that makes
    /// a replayed conversion return the existing booking instead of creating a second one.</summary>
    Task<long?> GetBookingIdByRequestIdAsync(long bookingRequestId, CancellationToken cancellationToken);

    /// <summary>The three frozen amounts + nurse for a booking — what b10's card-capture ledger group posts
    /// against when the booking already exists (idempotent confirm). NULL when absent.</summary>
    Task<BookingLedgerAmounts?> GetLedgerAmountsAsync(long id, CancellationToken cancellationToken);

    // ---- detail + lists ----
    Task<BookingDetailProjection?> GetDetailAsync(long id, CancellationToken cancellationToken);
    Task<PagedResult<BookingListItemDto>> ListForCustomerAsync(long customerId, string? status, int page, int pageSize, CancellationToken cancellationToken);
    Task<PagedResult<BookingListItemDto>> ListForNurseAsync(long nurseId, string? status, int page, int pageSize, CancellationToken cancellationToken);
    Task<PagedResult<BookingListItemDto>> ListAllAsync(string? status, int page, int pageSize, CancellationToken cancellationToken);

    /// <summary>Both participant user ids for a booking — the notification recipients. Null when absent.</summary>
    Task<BookingParticipants?> GetParticipantsAsync(long bookingId, CancellationToken cancellationToken);

    // ---- tracked loads for writes ----
    /// <summary>Tracked booking with its sessions loaded — for the transition guard and whole-booking cancel.</summary>
    Task<Booking?> GetTrackedWithSessionsAsync(long id, CancellationToken cancellationToken);

    /// <summary>Tracked booking with its 1:1 care instructions loaded — for the care-instructions upsert.</summary>
    Task<Booking?> GetTrackedWithCareAsync(long id, CancellationToken cancellationToken);

    /// <summary>The tracked booking that owns <paramref name="sessionId"/>, with all its sessions and their
    /// EVV records loaded, so a check-in/out/cancel can mutate the target session, create/complete its EVV,
    /// and evaluate the sibling sessions for booking completion. Null if the session is absent.</summary>
    Task<Booking?> GetTrackedBookingBySessionAsync(long sessionId, CancellationToken cancellationToken);

    // ---- care instructions (gated read) ----
    Task<CareInstructionsGate?> GetCareInstructionsGateAsync(long bookingId, CancellationToken cancellationToken);

    // ---- sessions + EVV ----
    Task<PagedResult<BookingSessionListItemDto>> ListSessionsForNurseAsync(long nurseId, DateOnly? date, int page, int pageSize, CancellationToken cancellationToken);
    Task<EvvGate?> GetEvvForSessionAsync(long sessionId, CancellationToken cancellationToken);
    Task<PagedResult<AdminEvvItemDto>> ListAdminEvvAsync(string type, int page, int pageSize, CancellationToken cancellationToken);

    /// <summary>Tracked scheduled sessions on or before <paramref name="today"/> with their booking loaded —
    /// the no-show sweep filters by the exact start-plus-threshold instant in memory (a DateOnly+TimeOnly
    /// combine is not translatable), then marks the overdue ones missed.</summary>
    Task<IReadOnlyList<BookingSession>> GetNoShowCandidatesAsync(DateOnly today, int batchSize, CancellationToken cancellationToken);
}
