using adas_core.Application.Repositories.Interfaces;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Infrastructure.Repositories;

/// <summary>
/// Represents a MongoDB-backed repository for managing <see cref="PatientCarePlan"/> entities,
/// providing concrete persistence operations defined by the <see cref="IPatientCarePlanRepository"/> contract.
/// </summary>
/// <typeparam name="PatientCarePlan">The type of the patient care plan entity managed by this repository.</typeparam>
/// <!-- aidoc-review:v1 severity=medium kind=extra_param
///      "<typeparam name=\"PatientCarePlan\"> is invalid because PatientCarePlanRepository is not a generic class; PatientCarePlan is a concrete type argument to MongoRepository<T>, not a type parameter." -->
public class PatientCarePlanRepository : MongoRepository<PatientCarePlan>, IPatientCarePlanRepository
{
    #region Properties

    private readonly ApiSettings _apiSettings;

    #endregion

    #region Update

    /// <summary>
    /// Asynchronously updates multiple object identifiers for a patient by delegating to the underlying asynchronous operation.
    /// </summary>
    /// <param name="patientid">The string identifier of the patient whose object identifiers will be updated.</param>
    /// <param name="patientId">The new <see cref="ObjectId"/> to assign to the patient's records.</param>
    /// <param name="oldId">The existing <see cref="ObjectId"/> to be replaced.</param>
    /// <!-- aidoc:v1 sig=9a63bf8 body=94ba0df -->
    public async Task UpdateManyObjectId(string patientid, ObjectId patientId, ObjectId oldId)
        {
            await UpdateManyObjectIdAsync(patientid, patientId, oldId);
        }

    #endregion

    #region Constructor

    

    /// <summary>
    /// Initializes a new instance of the <see cref="PatientCarePlanRepository"/> class with the supplied API configuration and MongoDB database connection, forwarding the database to the base repository.
    /// </summary>
    /// <param name="apiSettings">The <see cref="IOptions{ApiSettings}"/> providing the <see cref="ApiSettings"/> assigned to the repository.</param>
    /// <param name="database">The <see cref="IMongoDatabase"/> connection passed to the base class for data access.</param>
    /// <!-- aidoc:v1 sig=ab4ee14 body=12fddac -->
    public PatientCarePlanRepository(
        IOptions<ApiSettings> apiSettings,
        IMongoDatabase database
    ) : base(database)
    {
        _apiSettings = apiSettings.Value;
    }

    #endregion

    #region Read

    /// <summary>
    /// Returns the collection name for patient care plan data, using the configured setting if available or a default fallback otherwise.
    /// </summary>
    /// <returns>The patient care plan collection name from <c>_apiSettings.PatientCarePlan</c>, or <c>"patients_care_plan"</c> when the setting is null.</returns>
    /// <!-- aidoc:v1 sig=94e22ff body=c8bc19f -->
    public override string GetCollectionName()
        {
            return _apiSettings.PatientCarePlan ?? "patients_care_plan";
        }

    /// <summary>
    /// Retrieves all care plans associated with the specified patient identifier from the data store.
    /// Returns an empty list when no matching care plans exist for the patient.
    /// </summary>
    /// <param name="patientId">The unique identifier of the patient whose care plans should be retrieved.</param>
    /// <returns>A task that represents the asynchronous operation. The task result contains a list of <see cref="PatientCarePlan"/> objects associated with the specified patient, or an empty list if none are found.</returns>
    /// <!-- aidoc:v1 sig=9706d89 body=fae3443 -->
    public async Task<List<PatientCarePlan>> FindByPatientId(ObjectId patientId)
        {
            var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientId, patientId));
            return result.ToList();
        }

    /// <summary>
    /// Retrieves all patient care plans associated with the specified user identifier from the collection.
    /// </summary>
    /// <param name="userId">The unique identifier of the user whose patient care plans are being queried.</param>
    /// <returns>A list of <see cref="PatientCarePlan"/> instances matching the specified user identifier; an empty list is returned if no plans are found.</returns>
    /// <!-- aidoc:v1 sig=7520aa9 body=3dd56f3 -->
    public async Task<List<PatientCarePlan>> FindByUserId(ObjectId userId)
        {
            var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.UserId, userId));
            return result.ToList();
        }

    /// <summary>
    /// Retrieves all patient care plans from the data store without applying any filter.
    /// </summary>
    /// <returns>A task that represents the asynchronous operation, containing a list of all <see cref="PatientCarePlan"/> records.</returns>
    /// <!-- aidoc:v1 sig=6a558a7 body=faea989 -->
    public async Task<List<PatientCarePlan>> FindAll()
        {
            var result = await Collection.Find(Builders<PatientCarePlan>.Filter.Empty).ToListAsync();
            return result;
        }

    #endregion
}