using Netina.Domain.MartenEntities.Pages;

namespace Netina.Core.CoreServices;

public class PageService : IPageService
{
    private readonly IMartenRepositoryWrapper _martenRepositoryWrapper;
    private readonly ICurrentUserService _currentUserService;

    public PageService(IMartenRepositoryWrapper martenRepositoryWrapperWrapper, ICurrentUserService currentUserService)
    {
        _martenRepositoryWrapper = martenRepositoryWrapperWrapper;
        _currentUserService = currentUserService;
    }
    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.Title == 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,
            Title = page.Title,
            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 dto = new BasePageSDto
            {
                Content = page.Content,
                Description = page.Description,
                Id = page.Id,
                IsCustomPage = page.IsCustomPage,
                IsHtmlBasePage = page.IsHtmlBasePage,
                Title = page.Title,
                Slug = page.Slug,
                Data = page.Data,
                CreatedAt = page.CreatedAt,
                ModifiedAt = page.ModifiedAt
            };
            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 = Guid.NewGuid(),
            IsCustomPage = entity.IsCustomPage,
            IsHtmlBasePage = entity.IsHtmlBasePage,
            Title = entity.Title,
            Type = entity.Type,
            Slug = entity.Slug,
            CreatedAt = DateTime.Now,
            CreatedBy = _currentUserService.UserName ?? string.Empty
        };
        if (!basePage.Type.IsNullOrEmpty())
        {
            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;
    }

    public async Task<bool> DeletePageAsync(Guid id, CancellationToken cancellationToken = default)
    {
        var page = await _martenRepositoryWrapper.SetRepository<BasePage>().GetEntityAsync(p => p.Id == id, cancellationToken);
        if (page == null)
            throw new AppException("Page not found", ApiResultStatusCode.NotFound);
        await _martenRepositoryWrapper.SetRepository<BasePage>().RemoveEntityAsync(page,cancellationToken);
        return true;
    }
}