<?php

namespace App\Repository\Blog;

use App\Entity\Blog\Post;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class PostRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Post::class);
    }

    public function getEm()
    {
        return $this->getEntityManager();
    }

    public function findSimilarPosts(Post $post, int $quantity = 5): array
    {
        $query1 = $this->createQueryBuilder('p');
        $query2 = $this->createQueryBuilder('p');
        $categories = $post->getCategories()->getValues();
        $tags = $post->getTags();

        $query1->orderBy('p.publishedAt', 'DESC');

        if (count($tags)) {
            foreach ($tags as $k => $entity) {
                $query1
                    ->orWhere('p.tags LIKE :tag'.$k)
                    ->setParameter(':tag'.$k, '%"'.$entity['label'].'"%')
                ;
            }

            $search1 = $query1->getQuery()->getResult();
        } else {
            $search1 = [];
        }

        if (count($categories)) {
            $query2
                ->orderBy('p.publishedAt', 'DESC')
                ->andWhere('p.status = 1')
                ->join('p.categories', 'c')
                ->where('c.id IN (:ids)')
                ->setParameter(':ids', array_map(
                    fn ($e) => $e->getId(),
                    $categories
                ))
            ;

            $search2 = $query2->getQuery()->getResult();
        } else {
            $search2 = [];
        }

        $now = new \DateTime();
        $posts = [];

        foreach ([$search1, $search2] as $results) {
            foreach ($results as $result) {
                if (count($posts) === $quantity) {
                    continue 2;
                }

                if ($result->getId() === $post->getId()) {
                    continue;
                }

                if (Post::DRAFT === $result->getStatus()) {
                    continue;
                }

                if (null === $result->getPublishedAt()) {
                    continue;
                }

                if (null === $result->getImage()) {
                    continue;
                }

                if ($result->getPublishedAt() > $now) {
                    continue;
                }

                if (!isset($posts[$result->getId()])) {
                    $posts[$result->getId()] = $result;
                }
            }
        }

        return $posts;
    }
}
