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

namespace Baya.Application.Contracts.Persistence;

/// <summary>
/// Persistence for the verification pipeline. Tracked getters (for the state-changing handlers) load the
/// aggregate <see cref="NurseVerification"/> with its steps so the finalize transaction can flip
/// <c>nurse_profiles.is_verified</c> in one <c>SaveChanges</c>. Read getters are projected + paginated;
/// document-bearing reads take a <paramref name="signUrl"/> so signed GET URLs are minted without the
/// repository depending on the storage seam.
/// </summary>
public interface IVerificationRepository
{
    // --- Step-type catalog ---
    Task<VerificationStepType?> GetStepTypeByIdAsync(long id, CancellationToken cancellationToken);
    Task<bool> StepTypeCodeExistsAsync(string code, CancellationToken cancellationToken);
    Task<bool> StepTypeInUseAsync(long stepTypeId, CancellationToken cancellationToken);
    Task AddStepTypeAsync(VerificationStepType stepType, CancellationToken cancellationToken);
    Task<IReadOnlyList<VerificationStepTypeDto>> ListStepTypesAsync(bool includeInactive, CancellationToken cancellationToken);
    Task<IReadOnlyList<VerificationStepType>> GetActiveRequiredStepTypesAsync(CancellationToken cancellationToken);

    // --- Nurse verification aggregate (tracked, for mutation) ---
    Task<NurseVerification?> GetTrackedByNurseIdAsync(long nurseId, CancellationToken cancellationToken);
    Task<NurseVerification?> GetTrackedByIdAsync(long nurseVerificationId, CancellationToken cancellationToken);
    Task AddVerificationAsync(NurseVerification verification, CancellationToken cancellationToken);

    /// <summary>Tracked step scoped to the nurse (tenancy) with its step-type loaded; null if not owned.</summary>
    Task<VerificationStep?> GetTrackedStepForNurseAsync(long stepId, long nurseId, CancellationToken cancellationToken);

    /// <summary>Tracked step with its parent verification (and all sibling steps) + step-type, for an admin
    /// decision that must re-aggregate the whole verification.</summary>
    Task<VerificationStep?> GetTrackedStepWithVerificationAsync(long stepId, CancellationToken cancellationToken);

    // --- Documents / credentials ---
    Task AddDocumentAsync(VerificationDocument document, CancellationToken cancellationToken);
    Task AddCredentialAsync(NurseCredential credential, CancellationToken cancellationToken);

    /// <summary>Tracked credential for the nurse of a given type — lets the nurse-facing credential-details
    /// capture upsert (rather than duplicate) its registry row. Null when none exists yet.</summary>
    Task<NurseCredential?> GetTrackedCredentialAsync(long nurseId, string credentialType, CancellationToken cancellationToken);

    // --- Projected reads ---
    Task<VerificationStatusDto?> GetStatusForNurseAsync(long nurseId, CancellationToken cancellationToken);
    Task<PagedResult<AdminPendingStepDto>> ListPendingStepsAsync(
        VerificationStepStatus? status, int page, int pageSize, Func<string, string> signUrl, CancellationToken cancellationToken);
    Task<AdminVerificationDetailDto?> GetDetailAsync(long nurseVerificationId, Func<string, string> signUrl, CancellationToken cancellationToken);
    Task<TrustBadgeDto?> GetTrustBadgeAsync(long nurseId, DateOnly today, CancellationToken cancellationToken);

    /// <summary>The nurse's verified identity name ("Name FamilyName") for the credential holder cross-check.</summary>
    Task<string?> GetNurseIdentityNameAsync(long nurseId, CancellationToken cancellationToken);

    /// <summary>Tracked <c>users</c> row for the signed-in nurse — the identity-KYC step populates
    /// <c>national_id</c> + <c>national_id_verified_at</c> and Shahkar sets <c>shahkar_verified_at</c> on it.</summary>
    Task<Baya.Domain.Entities.User.User?> GetTrackedUserAsync(int userId, CancellationToken cancellationToken);

    /// <summary>Passed, time-limited steps whose expiry has lapsed — the expiry-scan worklist (paginated).</summary>
    Task<IReadOnlyList<ExpiringStepRow>> GetExpiredPassedStepsAsync(
        DateTimeOffset asOf, int page, int pageSize, CancellationToken cancellationToken);
}

/// <summary>An expired, previously-passed step that the scanner must revert + re-gate.</summary>
public readonly record struct ExpiringStepRow(long StepId, long NurseVerificationId, long NurseId);
