using adas_core.Application.Exceptions;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using MongoDB.Driver;

namespace adas_core.Application.Services;

public class HistoricalConfigChangesService(
    IHistoricalConfigChangesRepository historicalConfigChangesRepository,
    ILogger<HistoricalConfigChangesService> logger,
    IHttpContextAccessor httpContextAccessor,
    ILocalAuditService auditService)
    : IHistoricalConfigChangesService
{
    private readonly ILogger<HistoricalConfigChangesService> _logger = logger;

    public async Task DeleteHistoricalConfigChange(ObjectId id)
    {
        var filter = Builders<HistoricalConfigChanges>.Filter.Eq("_id", id);
        var result = historicalConfigChangesRepository.FindById(id);
        await historicalConfigChangesRepository.Collection.DeleteOneAsync(filter);
        _logger.LogInformation("Deleted historicalConfigChanges with id: {id}", id);
        await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, result, null);
    }

    public async Task<HistoricalConfigChanges?> FindLastConfigChanges(DisplayConfigEnums.ConfigTypes configType)
    {
        var result = await historicalConfigChangesRepository.FindLastHistoricalConfigChangesByType(configType);

        return result.FirstOrDefault();
    }

    public async Task<HistoricalConfigChanges?> Get(ObjectId id)
    {
        return await historicalConfigChangesRepository.FindById(id);
    }

    public async Task<ICollection<HistoricalConfigChanges>> GetAll()
    {
        return await historicalConfigChangesRepository.FindAll();
    }

    public async Task<ICollection<HistoricalConfigChanges>> GetByType(DisplayConfigEnums.ConfigTypes type, int num = 10)
    {
        return await historicalConfigChangesRepository.FindLastHistoricalConfigChangesByType(type, num);
    }


    public async Task<ICollection<HistoricalConfigChanges>> GetByUser(string user,
        DisplayConfigEnums.ConfigTypes? configTypes = null, int num = 10)
    {
        return await historicalConfigChangesRepository.FindLastHistoricalConfigChangesByUser(user, configTypes, num);
    }

    public async Task<HistoricalConfigChanges?> InsertOne(HistoricalConfigChanges historicalConfigChanges)
    {
        try
        {
            var result = await historicalConfigChangesRepository.InsertOneAsync(historicalConfigChanges) ??
                         throw new ConflictException(HttpEnum.ErrorMessage.ConflictCreationFailed);
            await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, null, result);
            return await historicalConfigChangesRepository.InsertOneAsync(historicalConfigChanges);
        }
        catch (Exception ex)
        {
            _logger.LogError("Exception inserting historicalConfigChanges {changes} exception:{e} ",
                historicalConfigChanges.ToJson(), ex);
            return null;
        }
    }

    public async Task<HistoricalConfigChanges?> UpdateHistoricalConfigChange(
        HistoricalConfigChanges historicalConfigChanges)
    {
        try
        {
            var oldHistorical = await historicalConfigChangesRepository.FindById(historicalConfigChanges.Id) ??
                                throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed);
            var result = await historicalConfigChangesRepository.Update(historicalConfigChanges);
            await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldHistorical, result);
            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError("Exception updating historicalConfigChanges {changes} exception:{e} ",
                historicalConfigChanges.ToJson(), ex);
            return null;
        }
    }

    public async Task LogConfigChanged(string user, DisplayConfigEnums.ConfigTypes configType, string newConfig,
        string oldConfig)
    {
        HistoricalConfigChanges historicalConfigChanges = new()
        {
            ConfigType = configType,
            Time = DateTime.Now,
            Username = user,
            OldConfig = oldConfig,
            NewConfig = newConfig
        };

        var result = await InsertOne(historicalConfigChanges);
        if (result == null)
            _logger.LogError("Error logging config changes. newConfig: {newConfig}, oldConfig: {oldConfig}",
                historicalConfigChanges.NewConfig, historicalConfigChanges.OldConfig);
        else
            _logger.LogDebug("Config changes logged. newConfig: {newConfig}, oldConfig: {oldConfig}",
                historicalConfigChanges.NewConfig, historicalConfigChanges.OldConfig);
    }
}