namespace Netina.Core.CoreServices;


public class SettingService : ISettingService
{
    private readonly IMartenRepositoryWrapper _martenRepositoryWrapper;

    public SettingService(IMartenRepositoryWrapper martenRepositoryWrapper)
    {
        _martenRepositoryWrapper = martenRepositoryWrapper;
    }

    public async Task<object> GetSettingAsync(string settingName, CancellationToken cancellationToken = default)
    {
        var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"Netina.Domain.MartenEntities.Settings.{settingName}");
        if (type == null)
            throw new AppException("Setting not found", ApiResultStatusCode.NotFound);

        var baseSetting = await _martenRepositoryWrapper.SetRepository<BaseSetting>()
            .GetEntityAsync(s => s.Name == settingName, cancellationToken);
        object? setting;
        if (baseSetting == null)
            setting = Activator.CreateInstance(type);
        else
            setting = JsonConvert.DeserializeObject(baseSetting.JsonData, type) ?? Activator.CreateInstance(type);

        if (setting == null)
            throw new AppException("Setting type or base is wrong");

        return setting;
    }

    public async Task CreateOrUpdateSettingAsync(string settingName, JsonDocument settingObj, CancellationToken cancellationToken = default)
    {
        var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"Netina.Domain.MartenEntities.Settings.{settingName}");
        if (type == null)
            throw new AppException("Setting not found", ApiResultStatusCode.NotFound);

        var baseSetting = await _martenRepositoryWrapper.SetRepository<BaseSetting>()
            .GetEntityAsync(s => s.Name == settingName, cancellationToken);

        if (baseSetting == null)
        {
            baseSetting = new BaseSetting
            {
                JsonData = JsonConvert.SerializeObject(settingObj.Deserialize(type)),
                Name = settingName,
                DotnetType = type.FullName ?? $"Netina.Domain.MartenEntities.Settings.{settingName}"
            };
        }
        else
        {
            baseSetting.JsonData = JsonConvert.SerializeObject(settingObj.Deserialize(type));
        }

        await _martenRepositoryWrapper.SetRepository<BaseSetting>()
            .AddOrUpdateEntityAsync(baseSetting, cancellationToken);
    }
}