using Netina.Common.Models.Api;
using Netina.Common.Models.Exception;
using Netina.Core.CoreServices.Abstracts;
using Netina.Domain;
using Netina.Domain.Dtos.RequestDtos;
using Netina.Domain.Dtos.SmallDtos;
using Netina.Domain.MartenEntities.Pages;
using Netina.Repository.Repositories.Marten;

namespace Netina.Core.CoreServices;

public class PageService : IPageService
{
    private readonly IMartenRepositoryWrapper _martenRepositoryWrapper;

    public PageService(IMartenRepositoryWrapper martenRepositoryWrapperWrapper)
    {
        _martenRepositoryWrapper = martenRepositoryWrapperWrapper;
    }
    public async Task<BasePageSDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default)
    {
        BasePage? page = null;
        if (id != null)
            page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(id.Value, cancellationToken);
        else if (pageSlug != null)
            page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Slug == pageSlug, cancellationToken);
        else if (pageName != null)
            page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Name == pageName, cancellationToken);
        else if (type != null)
            page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(entity => entity.Type == type, cancellationToken);
        if (page == null)
            throw new AppException("Page not found", ApiResultStatusCode.NotFound);

        var entityType = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(page.Type);
        var dto = new BasePageSDto
        {
            Content = page.Content,
            Description = page.Description,
            Id = page.Id,
            IsCustomPage = page.IsCustomPage,
            IsHtmlBasePage = page.IsHtmlBasePage,
            Name = page.Name,
            Slug = page.Slug,
            Data = page.Data
        };

        return dto;
    }

    public async Task<List<BasePageSDto>> GetPagesAsync(CancellationToken cancellationToken = default)
    {
        List<BasePageSDto> sDtos = new List<BasePageSDto>();
        var pages = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntitiesAsync(cancellationToken);
        foreach (var page in pages)
        {

            var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(page.Type);
            var dto = new BasePageSDto
            {
                Content = page.Content,
                Description = page.Description,
                Id = page.Id,
                IsCustomPage = page.IsCustomPage,
                IsHtmlBasePage = page.IsHtmlBasePage,
                Name = page.Name,
                Slug = page.Slug,
                Data = page.Data
            };
            sDtos.Add(dto);
        }
        return sDtos;
    }

    public async Task<bool> CreatePageAsync(PageActionRequestDto entity, CancellationToken cancellationToken = default)
    {
        var basePage = new BasePage
        {
            Content = entity.Content,
            Description = entity.Description,
            Id = entity.Id,
            IsCustomPage = entity.IsCustomPage,
            IsHtmlBasePage = entity.IsHtmlBasePage,
            Name = entity.Name,
            Type = entity.Type,
            Slug = entity.Slug,
        };
        var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(entity.Type);
        basePage.Data = JsonConvert.SerializeObject(((JsonElement)entity.Data).Deserialize(type));
        await _martenRepositoryWrapper.SetRepository<BasePage>().AddOrUpdateEntityAsync(basePage, cancellationToken);
        return true;
    }
}