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

namespace adas_core.Infrastructure.Repositories;

/// <summary>
/// Repository for managing ConfigPumps in MongoDB. Provides methods to retrieve, update, and delete pump configurations.
/// </summary>
public class ConfigPumpsRepository : MongoRepository<ConfigPumps>, IConfigPumpsRepository
{
    private readonly ApiSettings _apiSettings;

    /// <summary>
    /// Initializes a new instance of the ConfigPumpsRepository class with the specified API settings and MongoDB database.
    /// </summary>
    /// <param name="apiSettings">The API settings.</param>
    /// <param name="database">The MongoDB database instance.</param>
    /// <exception cref="ArgumentNullException">Thrown when apiSettings is null.</exception>
    public ConfigPumpsRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
    {
        if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
        _apiSettings = apiSettings.Value;
    } //For testing


    /// <summary>
    /// Gets the name of the MongoDB collection for ConfigPumps. Uses the value from API settings or defaults to "config_pumps".
    /// </summary>
    /// <returns>The name of the MongoDB collection for ConfigPumps.</returns>
    public override string GetCollectionName()
    {
        return _apiSettings.ConfigPumps ?? "config_pumps";
    }

    /// <summary>
    /// Retrieves all ConfigPumps documents from the MongoDB collection. Returns a list of ConfigPumps or null if no documents are found.
    /// </summary>
    /// <returns>A list of ConfigPumps or null if no documents are found.</returns>
    public async Task<List<ConfigPumps>?> GetAllConfigs()
    {
        var result = await Collection.FindAsync(Builders<ConfigPumps>.Filter.Empty);

        return result.ToList();
    }

    /// <summary>
    /// Finds a ConfigPumps document by its unique identifier. Returns the ConfigPumps if found, or null if not found.
    /// </summary>
    /// <param name="id">The unique identifier of the ConfigPumps document.</param>
    /// <returns>The ConfigPumps document if found, or null if not found.</returns>
    public async Task<ConfigPumps?> FindById(string id)
    {
        var result = await Collection.FindAsync(Builders<ConfigPumps>.Filter.Eq(x => x.Id, id));

        return await result.FirstOrDefaultAsync();
    }

    /// <summary>
    /// Updates an existing ConfigPumps document in the MongoDB collection. 
    /// The method takes a ConfigPumps object, updates the corresponding document based on its Id, and returns the updated ConfigPumps. 
    /// If the document is not found, it returns null.
    /// </summary>
    /// <param name="config">The ConfigPumps object containing the updated data.</param>
    /// <returns>The updated ConfigPumps document if found, or null if not found.</returns>
    public async Task<ConfigPumps?> UpdateConfig(ConfigPumps config)
    {
        var filter = Builders<ConfigPumps>.Filter.Eq("_id", config.Id);
        var update = Builders<ConfigPumps>.Update.Set(c => c.Items, config.Items);

        return await Collection.FindOneAndUpdateAsync(filter, update,
            new FindOneAndUpdateOptions<ConfigPumps, ConfigPumps> { ReturnDocument = ReturnDocument.After });
    }

    /// <summary>
    /// Deletes a ConfigPumps document from the MongoDB collection based on its Id. 
    /// The method takes a ConfigPumps object, deletes the corresponding document, and returns true if the deletion was successful (i.e., the document no longer exists), or false if the document still exists after the deletion attempt.
    /// </summary>
    /// <param name="config">The ConfigPumps object to be deleted.</param>
    /// <returns>True if the deletion was successful, false otherwise.</returns>
    public async Task<bool> DeleteConfig(ConfigPumps config)
    {
        var filter = Builders<ConfigPumps>.Filter.Eq("_id", config.Id);
        await Collection.DeleteOneAsync(filter);

        var result = await FindById(config.Id);
        return result == null;
    }
}