using System.Reflection;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc.RazorPages;
using NetinaShop.Domain;
using NetinaShop.Domain.Entities.Pages;
using NetinaShop.Repository.Repositories.Entity.Abstracts;

namespace NetinaShop.Core.CoreServices;

public class PageService : IPageService
{
    private readonly IMartenRepository _martenRepository;

    public PageService(IMartenRepository martenRepository)
    {
        _martenRepository = martenRepository;
    }
    public async Task<BasePageEntitySDto> GetPageAsync(Guid? id = null, string? pageName = null, string? pageSlug = null, string? type = null, CancellationToken cancellationToken = default)
    {
        BasePageEntity? page = null;
        if (id != null)
            page = await _martenRepository.GetEntityAsync<BasePageEntity>(id.Value, cancellationToken);
        else if (pageSlug != null)
            page = await _martenRepository.GetEntityAsync<BasePageEntity>(entity => entity.Slug == pageSlug, cancellationToken);
        else if (pageName != null)
            page = await _martenRepository.GetEntityAsync<BasePageEntity>(entity => entity.Name == pageName, cancellationToken);
        else if (type != null)
            page = await _martenRepository.GetEntityAsync<BasePageEntity>(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 BasePageEntitySDto
        {
            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<BasePageEntitySDto>> GetPagesAsync(CancellationToken cancellationToken = default)
    {
        List<BasePageEntitySDto> sDtos = new List<BasePageEntitySDto>();
        var pages = await _martenRepository.GetEntitiesAsync<BasePageEntity>(cancellationToken);
        foreach (var page in pages)
        {

            var type = Assembly.GetAssembly(typeof(DomainConfig))?.GetType(page.Type);
            var dto = new BasePageEntitySDto
            {
                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 BasePageEntity
        {
            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 _martenRepository.AddOrUpdateEntityAsync(basePage, cancellationToken);
        return true;
    }
}