package com.ecep.contract;

import com.ecep.contract.ds.MyRepository;
import com.ecep.contract.model.Contract;
import com.ecep.contract.util.SpecificationUtils;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;

import java.util.List;

public abstract class EntityService<T, ID> {

    protected abstract MyRepository<T, ID> getRepository();

    public abstract T createNewEntity();


    public long count() {
        return getRepository().count();
    }

    public long count(Specification<T> spec) {
        return getRepository().count(spec);
    }

    public long count(JsonNode paramsNode) {
        return getRepository().count(buildParameterSpecification(paramsNode));
    }

    protected abstract Specification<T> buildParameterSpecification(JsonNode paramsNode);

    public Page<T> findAll(JsonNode paramsNode, Pageable pageable) {
        Specification<T> spec = null;
        if (paramsNode.has("searchText")) {
            spec = getSpecification(paramsNode.get("searchText").asText());
        }
        spec = SpecificationUtils.and(spec, buildParameterSpecification(paramsNode));
        return findAll(spec, pageable);
    }


    public Page<T> findAll(Specification<T> spec, Pageable pageable) {
        return getRepository().findAll(spec, pageable);
    }

    public List<T> findAll(Specification<T> spec, Sort sort) {
        return getRepository().findAll(spec, sort);
    }

    protected abstract Specification<T> buildSearchSpecification(String searchText);

    public Specification<T> getSpecification(String searchText) {
        if (!StringUtils.hasText(searchText)) {
            return null;
        }
        return SpecificationUtils.andWith(searchText, this::buildSearchSpecification);
    }

    public List<T> search(String searchText) {
        Specification<T> spec = getSpecification(searchText);
        return getRepository().findAll(spec, Pageable.ofSize(10)).getContent();
    }
}
