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

namespace adas_core.Infrastructure.Repositories;

public class DiagnosisRepository : MongoRepository<PatientDiagnosis>, IDiagnosisRepository
{
    private readonly ApiSettings _apiSettings;


    public DiagnosisRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
    {
        if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
        _apiSettings = apiSettings.Value;
    } //For testing


    public override string GetCollectionName()
    {
        return _apiSettings.PatientsDiagnosis ?? "patients_diagnosis";
    }

    public async Task<List<PatientDiagnosis>> GetByPatient(ObjectId patientId)
    {
        var filter = Builders<PatientDiagnosis>.Filter.Eq(ob => ob.PatientId, patientId);
        var result = await Collection.FindAsync(filter,
            new FindOptions<PatientDiagnosis> { Sort = Builders<PatientDiagnosis>.Sort.Descending("time") });

        return result.ToList();
    }

    public new async Task DeleteAsync(ObjectId id)
    {
        var filter = Builders<PatientDiagnosis>.Filter.Eq(t => t.Id, id);
        await Collection.DeleteOneAsync(filter);
    }


    public override async Task InsertOneAsync(PatientDiagnosis diagnosis)
    {
        await Collection.InsertOneAsync(diagnosis);
    }

    public async Task DeleteByPatientId(ObjectId patientId)
    {
        var filter = Builders<PatientDiagnosis>.Filter.Eq(po => po.PatientId, patientId);
        await Collection.DeleteManyAsync(filter);
    }

    public async Task<PatientDiagnosis?> FindByPatientIdAndCode(ObjectId patientId, string? code, string? codingSystem)
    {
        var builder = Builders<PatientDiagnosis>.Filter;
        var filter = builder.And(
            builder.Eq(ob => ob.PatientId, patientId),
            builder.Eq(ob => ob.Code, code),
            builder.Eq(ob => ob.CodingSystem, codingSystem)
        );

        var result = await Collection.FindAsync(filter);

        return await result.FirstOrDefaultAsync();
    }


    public async Task<IAsyncCursor<PatientDiagnosis>> FindByPatientIdAsync(ObjectId patientId)
    {
        var filter = Builders<PatientDiagnosis>.Filter.Eq(ob => ob.PatientId, patientId);

        return await Collection.FindAsync(filter);
    }

    public async Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId)
    {
        await UpdateManyObjectIdAsync(nameId, id, oldId);
    }

    public override async Task CreateIndexes()
    {
        var options = new CreateIndexOptions { Background = true, Unique = false };
        var indexes = new List<CreateIndexModel<PatientDiagnosis>>
        {
            new("{ patientid: 1 }", options)
        };

        await MongoUtils.EnsureIndexes(Collection, indexes);
    }
}