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

namespace adas_core.Infrastructure.Repositories;

public class PoCSettingsRepository : MongoRepository<PoCSettings>, IPoCSettingsRepository
{
    private readonly ApiSettings _apiSettings;

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


    public override string GetCollectionName()
    {
        return _apiSettings.PoCSettings ?? "poc_settings";
    }

    public async Task Delete(ObjectId id)
    {
        try
        {
            var filter = Builders<PoCSettings>.Filter.Eq(x => x.Id, id);
            await Collection.DeleteOneAsync(filter, null);
        }
        catch (Exception ex)
        {
            Log.Error("Error deleting PoCSettings by id: {id}. Exception: {ex}", id, ex);
            throw;
        }
    }

    public async Task<List<PoCSettings>> FindAll()
    {
        try
        {
            return (await Collection.FindAsync(Builders<PoCSettings>.Filter.Empty)).ToList();
        }
        catch (Exception ex)
        {
            Log.Error("Error searching PoCSettings. Exception: {ex}", ex);

            return [];
        }
    }

    public async Task<PoCSettings?> FindById(ObjectId id)
    {
        try
        {
            var filter = Builders<PoCSettings>.Filter.Eq(p => p.Id, id);
            var result = await Collection.FindAsync(filter);

            return await result.FirstOrDefaultAsync();
        }
        catch (Exception ex)
        {
            Log.Error("Error searching PoCSettings by id: {id}. Exception: {ex}", id, ex);
            return null;
        }
    }

    public async Task<PoCSettings?> FindByLocation(PatientLocation location)
    {
        try
        {
            var filterBuilder = Builders<PoCSettings>.Filter;
            var filter = filterBuilder.Ne(p => p.PatientLocation, null);
            // TODO
            // if (!string.IsNullOrEmpty(location.PointOfCare) && !string.IsNullOrEmpty(location.Bed))
            // {
            //     filter = filterBuilder.And(
            //         filter,
            //         filterBuilder.Eq(p => p.PatientLocation!.PointOfCare, location.PointOfCare),
            //         filterBuilder.Eq(p => p.PatientLocation!.Bed, location.Bed)
            //     );
            // }                

            var result = await Collection.Find(filter).Limit(1).FirstOrDefaultAsync();

            return result;
        }
        catch (Exception ex)
        {
            Log.Debug("Error searching by location. Exception: {ex}", ex);
            throw;
        }
    }


    public async Task Update(PoCSettings pocSettings)
    {
        try
        {
            await UpdateOneAsync(pocSettings.Id, pocSettings);
        }
        catch (Exception ex)
        {
            Log.Debug("Error updating PoC Settings: {pocS}. Exception: {ex}", pocSettings.ToString(), ex);
            throw;
        }
    }

    public override async Task CreateIndexes()
    {
        var options = new CreateIndexOptions { Background = true, Unique = false };
        //var optionsUq = new CreateIndexOptions<PoCSettings>()
        //{
        //    Background = true,
        //    Unique = true,
        //    PartialFilterExpression = Builders<PoCSettings>.Filter.Exists(p => p.PatientLocation) &
        //                              Builders<PoCSettings>.Filter.Exists(p => p.ManualRelayStatus)
        //};
        var indexes = new List<CreateIndexModel<PoCSettings>>
        {
            new("{ patientLocation: 1 }", options)
            //new("{ relayStatus: 1, bed: 1 }", optionsUq)
        };

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