using System.Reflection;
using System.Text.Json;
using NetinaShop.Repository.Repositories.Entity.Abstracts;

namespace NetinaShop.Api.Controller;

public class SettingController : ICarterModule
{
    public void AddRoutes(IEndpointRouteBuilder app)
    {
        var group = app.NewVersionedApi("Setting")
            .MapGroup("api/setting")
            .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser());

        group.MapGet("{settingName}", GetSettingAsync)
            .WithDisplayName("GetSetting")
            .HasApiVersion(1.0);
        group.MapPost("{settingName}", PostSettingAsync)
            .WithDisplayName("PostSettingAsync")
            .HasApiVersion(1.0);
    }

    public async Task<IResult> GetSettingAsync(string settingName, [FromServices] IMartenRepository martenRepository, CancellationToken cancellationToken)
    {
        var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"NetinaShop.Domain.Entities.Settings.{settingName}");
        if (type == null)
            throw new AppException("Setting not found", ApiResultStatusCode.NotFound);

        var setting = await ((dynamic)martenRepository.GetType()?.GetMethod("GetEntityAsync")
            ?.MakeGenericMethod(type)
            .Invoke(martenRepository,new object[]{ cancellationToken })!);
        if (setting == null)
            setting = Activator.CreateInstance(type);

        return TypedResults.Ok(setting);
    }

    public async Task<IResult> PostSettingAsync(string settingName, [FromBody]JsonDocument settingObj, [FromServices] IMartenRepository martenRepository, CancellationToken cancellationToken)
    {
        var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType($"NetinaShop.Domain.Entities.Settings.{settingName}");
        if (type == null)
            throw new AppException("Setting not found", ApiResultStatusCode.NotFound);
        var setting = settingObj.Deserialize(type);
        if (setting == null)
            throw new AppException("Setting not found", ApiResultStatusCode.NotFound);
        await ((dynamic)martenRepository.GetType().GetMethod("AddOrUpdateEntityAsync")
            ?.MakeGenericMethod(type).Invoke(martenRepository, new[] { setting , cancellationToken })!);

        return TypedResults.Ok();
    }
}