package enea.lecservice.services;

import com.github.slugify.Slugify;
import enea.lecservice.models.Configuration;
import enea.lecservice.models.dto.ServiceResponse;
import enea.lecservice.models.dto.PageFilter;
import enea.lecservice.entities.Page;
import enea.lecservice.entities.PermissionEnum;
import enea.lecservice.repository.PageRepository;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class PageService {
    public final String DEFAULT_LANGUAGE = "it";
    @NonNull
    protected PageRepository pageRepository;

    public ServiceResponse createInitialData() {
        Page pagesEn = Page.builder()
                .name("Pages")
                .lang("en")
                .slug("pages")
                .path("pages")
                .showOrder(1)
                .visible(true)
                //.role(PermissionEnum.VIEW)
                .permissionId(PermissionEnum.VIEW.toString())
                .build();

        pageRepository.save(pagesEn);

        Page pagesIt = Page.builder()
                .name("Pagine")
                .lang("it")
                .slug("pages")
                .path("pages")
                .showOrder(1)
                .visible(true)
                //.permission(PermissionEnum.VIEW)
                .permissionId(PermissionEnum.VIEW.toString())
                .build();

        pageRepository.save(pagesIt);

        return ServiceResponse.Success();
    }

    public ServiceResponse<List<Page>> getAllPages() {
        return ServiceResponse.Success(pageRepository.findAllByDeletedFalseOrderByName());
    }

    public ServiceResponse<List<Page>> getForPermissions(String lang, List<String> permissions) {
        return ServiceResponse.Success(pageRepository.getPagesInPermissions(lang, permissions));
    }

    public ServiceResponse<Page> getPage(String lang, String id) {
        if (id == null || id.isBlank())
            return ServiceResponse.Error("Page ID not specified.");

        var page = pageRepository.findById(UUID.fromString(id));

        if (page.isEmpty())
            return ServiceResponse.Error("No page found.");

        return ServiceResponse.Success(page.get());
    }

    public ServiceResponse<Configuration> getPageConfiguration(String lang, String slug, List<String> permissions) {
        if (slug == null || slug.isBlank())
            return ServiceResponse.Error("Page slug not specified.");
        List<Page> pages = pageRepository.getPagesInPermissionsBySlugForAllLangs(slug, permissions);

        var page = pages.stream().filter(p -> lang.equals(p.getLang())).findFirst()
                .or( () -> pages.stream().filter(p -> DEFAULT_LANGUAGE.equals(p.getLang())).findFirst()
        );

        if (page.isEmpty())
            return ServiceResponse.Error("No page found.");

        return ServiceResponse.Success(page.map(Page::getConfiguration).orElse(null));
    }

    public ServiceResponse getPaginatedData(PageFilter filter) {
        org.springframework.data.domain.Page<Page> pagination = pageRepository.getPaginatedData(
                filter.getGlobalFilter(),
                PermissionEnum.VIEW,
                PageRequest.of(filter.getFirst()/filter.getRows(), filter.getRows(), Sort.Direction.ASC, "createdAt"));

        return ServiceResponse.Success(
                new Object () {
                    public List items = pagination.getContent();
                    public Long total = pagination.getTotalElements();
                }
        );
    }

    public ServiceResponse<Page> save(Page page) {
        Page dbItem = new Page();

        if (page.getId() != null)
            dbItem = pageRepository.getById(page.getId());

        if (StringUtils.isBlank(page.getSlug()))
            dbItem.setSlug(getUniqueSlug(page.getName()));
        else
            dbItem.setSlug(page.getSlug());

        if (!page.isDynamic())
            dbItem.setSlug(null);

        dbItem.setDynamic(page.isDynamic());
        dbItem.setShowInMenu(page.isShowInMenu());
        dbItem.setName(page.getName());
        dbItem.setPath(page.isDynamic() ? "pages/" + page.getSlug() : page.getPath());
        dbItem.setDefaultPage(page.isDefaultPage());
        dbItem.setVisible(page.isVisible());
        dbItem.setLang(page.getLang());
        dbItem.setConfiguration(page.getConfiguration());
        dbItem.setConfigurationTextFromConfiguration(page.getConfiguration());
        dbItem.setCommunityId(page.getCommunityId());
        dbItem.setPermissionId(StringUtils.isNotBlank(page.getPermissionId()) ? page.getPermissionId() : PermissionEnum.VIEW.toString());
        pageRepository.save(dbItem);

        return ServiceResponse.Success(dbItem);
    }

    public ServiceResponse delete(UUID id) {
        if (id == null) {
            return ServiceResponse.Error("Specificare l'id della pagina da eliminare!");
        }
        Page dbItem = pageRepository.getById(id);
        dbItem.setDeleted(true);
        pageRepository.save(dbItem);
        return ServiceResponse.Success();
    }

    public String getUniqueSlug(String fromValue) {
        int count = 1;
        Slugify slugify = new Slugify();
        String slug = slugify.slugify(fromValue);

        while (pageRepository.slugExists(slug)) {
            slug = String.format("%s-%s", slug, count);
            count ++;
        }

        return slug;
    }
}
