using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.Pumps;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Infrastructure.Repositories
{
    /// <summary>
    /// Repositorio de archivo para observaciones de bombas.
    /// Colección: archive_pumpobservations (configurable por ApiSettings.ArchivePumpObservations).
    /// </summary>
    public class PumpArchiveRepository : MongoRepository<PumpObservation>, IPumpArchiveRepository
    {
        private readonly ApiSettings _apiSettings;

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


        public override string GetCollectionName()
        {
            // Nombre de colección pactado: "archive_pumpobservations"
            return _apiSettings.ArchivePatientsPumpobservations ?? "archive_pumpobservations";
        }

        public override async Task CreateIndexes()
        {
            var indexModels = new List<CreateIndexModel<PumpObservation>>
            {
                // Búsquedas por paciente (audit / restauraciones)
                new CreateIndexModel<PumpObservation>(
                    Builders<PumpObservation>.IndexKeys.Ascending(x => x.PatientId),
                    new CreateIndexOptions { Name = "ix_patientId" }),

                // Timeline por dispositivo (útil para auditorías por equipo)
                new CreateIndexModel<PumpObservation>(
                    Builders<PumpObservation>.IndexKeys
                        .Ascending(x => x.DeviceId)
                        .Descending(x => x.Time),
                    new CreateIndexOptions { Name = "ix_deviceId_time" }),

                // Orden temporal simple
                new CreateIndexModel<PumpObservation>(
                    Builders<PumpObservation>.IndexKeys.Descending(x => x.Time),
                    new CreateIndexOptions { Name = "ix_time" })
            };

            await Collection.Indexes.CreateManyAsync(indexModels);
        }

        public async Task InsertAsync(PumpObservation obs)
        {
            await Collection.InsertOneAsync(obs);
        }

        public async Task InsertManyAsync(IEnumerable<PumpObservation> observations)
        {
            var list = observations as IList<PumpObservation> ?? observations.ToList();
            if (list.Count == 0) return;

            await Collection.InsertManyAsync(list);
        }

        public async Task<IEnumerable<PumpObservation>> FindByPatientIdAsync(
            ObjectId patientId, DateTime? from = null, DateTime? to = null, int? limit = null)
        {
            var filter = Builders<PumpObservation>.Filter.Eq(x => x.PatientId, patientId);

            if (from.HasValue)
                filter &= Builders<PumpObservation>.Filter.Gte(x => x.Time, from.Value);

            if (to.HasValue)
                filter &= Builders<PumpObservation>.Filter.Lte(x => x.Time, to.Value);

            var query = Collection.Find(filter).SortByDescending(x => x.Time);

            if (limit.HasValue)
                query = query.Limit(limit.Value) as IOrderedFindFluent<PumpObservation, PumpObservation>;

            return await query.ToListAsync();
        }

        public async Task DeleteBeforeDate(DateTime addDays)
        {
            var filter = Builders<PumpObservation>.Filter.Lt(x => x.Time, addDays);
            await Collection.DeleteManyAsync(filter);
        }
    }
}