package io.delphiplatform.api.v3.rdb.service.specification;

import org.springframework.data.jpa.domain.Specification;

import java.util.Collection;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;

import io.delphiplatform.api.util.CollectionUtils;
import io.delphiplatform.api.v3.model.video.YoutubeContentType;
import io.delphiplatform.api.v3.rdb.entity.video.VideoIsrcEntity;

public class VideoByIsrcsSpecification<T> implements Specification<T> {

    private final Collection<?> isrcs;
    private final Collection<YoutubeContentType> contentTypes;
    private final Long minPremiumUgcViews;

    protected VideoByIsrcsSpecification(Collection<?> isrcs, Collection<YoutubeContentType> contentTypes,
        Long minPremiumUgcViews) {
        this.isrcs = isrcs;
        this.contentTypes = contentTypes;
        this.minPremiumUgcViews = minPremiumUgcViews;
    }

    @Override
    public Predicate toPredicate(Root<T> r, CriteriaQuery<?> cq, CriteriaBuilder cb) {
        if (CollectionUtils.isEmpty(isrcs)) {
            return null;
        }

        Subquery<Object> subquery = cq.subquery(Object.class);
        Root<VideoIsrcEntity> subQueryFrom = subquery.from(VideoIsrcEntity.class);
        subquery.select(subQueryFrom.get("videoIsrcId").get("videoId"));

        if (CollectionUtils.isNotEmpty(contentTypes)) {
            subquery.where(
                cb.or(this.contentTypes.stream()
                    .map(ct -> cb.and(
                        VideoContentTypeSpecification.getContentTypePredicate(subQueryFrom, cb, ct, minPremiumUgcViews),
                        subQueryFrom.get("videoIsrcId").get("isrc").in(isrcs)
                    )).toArray(Predicate[]::new)));
        } else {
            subquery.where(subQueryFrom.get("videoIsrcId").get("isrc").in(isrcs));
        }

        return cb.isTrue(r.get("videoId").in(subquery));
    }

}
