using adas_core.Application.Repositories.Interfaces;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.MongoModels;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;

namespace adas_core.Infrastructure.Repositories;

public class ArchivePatientCarePlanRepository : MongoRepository<PatientCarePlan>, IArchivePatientCarePlanRepository
{
    #region Properties

    private readonly ApiSettings _apiSettings;
    private readonly ILogger<ArchivePatientCarePlanRepository> _logger;

    #endregion

    #region Constructor
    

    public ArchivePatientCarePlanRepository(
        IOptions<ApiSettings> apiSettings,
        IMongoDatabase database,
        ILogger<ArchivePatientCarePlanRepository> logger) : base(database)
    {
        _logger = logger;
        _apiSettings = apiSettings.Value;
    }

    public override async Task CreateIndexes()
    {
        var options = new CreateIndexOptions<PatientCarePlan> { Background = true, Unique = false };

        var indexes = new List<CreateIndexModel<PatientCarePlan>>
        {
            new("{ patientId: 1 }", options)
        };

        await MongoUtils.EnsureIndexes(Collection, indexes);
    }

    #endregion

    #region Create

    public override async Task InsertOneAsync(PatientCarePlan patient)
    {
        try
        {
            await base.InsertOneAsync(patient);
        }
        catch (Exception e)
        {
            _logger.LogError(
                "Exception trying to insert patient: {patient}. on archive patient procedure Exception {e}", patient,
                e);
            throw;
        }
    }

    public override async Task InsertManyAsync(List<PatientCarePlan> patient)
    {
        try
        {
            await base.InsertManyAsync(patient);
        }
        catch (Exception e)
        {
            _logger.LogError(
                "Exception trying to insert many PatientCarePlan. on archive patient procedure Exception {e}", e);
            throw;
        }
    }

    #endregion

    #region Read

    public override string GetCollectionName()
    {
        return _apiSettings.ArchivePatientProcedure ?? "archive_patients_care_plan";
    }

    public async Task<List<PatientCarePlan>?> FindByPatientId(ObjectId patientId)
    {
        var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientId, patientId));
        return result.ToList();
    }

    public async Task<List<PatientCarePlan>?> FindByPatientId(string patientId)
    {
        var isParsed = ObjectId.TryParse(patientId, out var patientIdParsed);
        if (!isParsed) return [];
        var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientId, patientIdParsed));
        return result.ToList();
    }

    public async Task<List<PatientCarePlan>?> FindByPatientNumber(string patientId)
    {
        var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientNumber, patientId));
        return result.ToList();
    }

    public async Task<List<PatientCarePlan>> FindAll()
    {
        var result = await Collection.Find(Builders<PatientCarePlan>.Filter.Empty).ToListAsync();
        return result;
    }

    public async Task<List<PatientCarePlan>?> FindByIds(ObjectId oldPatientId, string? oldPatientPatientId,
        string? oldPatientPatientNumber)
    {
        var patientFound = await FindByPatientId(oldPatientId);
        if (patientFound != null) return patientFound;
        if (oldPatientPatientId != null)
        {
            patientFound = await FindByPatientId(oldPatientPatientId);
            if (patientFound is { Count: > 0 }) return patientFound;
        }

        if (oldPatientPatientNumber != null)
        {
            patientFound = await FindByPatientNumber(oldPatientPatientNumber);
            if (patientFound is { Count: > 0 }) return patientFound;
        }

        return [];
    }

    #endregion

    #region Update

    // public async Task Update(Patient patient)
    // {
    //     patient.UpdateDate = DateTime.UtcNow;
    //     await UpdateOneAsync(patient.Id, patient);
    // }
    //
    // public async void UpdatePatientData(Patient oldPatient, Patient newPatient)
    // {
    //     var filterBuilder = Builders<Patient>.Filter;
    //     var updateBuilder = Builders<Patient>.Update
    //         .Set(p => p.Person, newPatient.Person)
    //         .Set(p => p.UpdateDate, DateTime.UtcNow)
    //         .Set(p => p.Location, newPatient.Location)
    //         .Set(p => p.PatientNumber, newPatient.PatientNumber)
    //         .Set(p => p.UnitString, newPatient.UnitString)
    //         .Set(p => p.Room, newPatient.Room)
    //         .Set(p => p.PatientId, newPatient.PatientId);
    //     var filter = filterBuilder.Eq(p => p.Id, oldPatient.Id);
    //     var update = updateBuilder;
    //
    //     await Collection.UpdateOneAsync(filter, update);
    // }

    // public async void UpdateProcedure(Patient patientFound)
    // {
    //     var filterBuilder = Builders<Patient>.Filter;
    //     var updateBuilder = Builders<Patient>.Update
    //         .Set(p => p.Procedures, patientFound.Procedures);
    //     var filter = filterBuilder.Eq(p => p.Id, patientFound.Id);
    //     var update = updateBuilder;
    //
    //     await Collection.UpdateOneAsync(filter, update);
    // }
    //
    // public async void UpdateTreatment(Patient patientFound)
    // {
    //     var filterBuilder = Builders<Patient>.Filter;
    //     var updateBuilder = Builders<Patient>.Update
    //         .Set(p => p.Treatment, patientFound.Treatment);
    //     var filter = filterBuilder.Eq(p => p.Id, patientFound.Id);
    //     var update = updateBuilder;
    //
    //     await Collection.UpdateOneAsync(filter, update);
    // }

    #endregion
}