<?php

namespace App\Repository\Blog;

use App\Core\Repository\RepositoryQuery;
use App\Entity\Blog\Category;
use Knp\Component\Pager\PaginatorInterface;

/**
 * class PostRepositoryQuery.
 *
 * @author Simon Vieille <simon@deblan.fr>
 */
class PostRepositoryQuery extends RepositoryQuery
{
    public function __construct(PostRepository $repository, PaginatorInterface $paginator)
    {
        parent::__construct($repository, 'p', $paginator);
    }

    public function inCategory(Category $category, bool $strict = true): self
    {
        $c = 'c'.mt_rand();

        if ($strict) {
            $this
                ->innerJoin('p.categories', $c)
                ->andWhere($c.'.id = :category')
                ->setParameter(':category', $category->getId())
            ;
        } else {
            $ids = [$category->getId()];

            foreach ($category->getCategories() as $childCategory) {
                $ids[] = $childCategory->getId();
            }

            $this
                ->innerJoin('p.categories', $c)
                ->andWhere($c.'.id IN (:categories)')
                ->setParameter(':categories', $ids)
            ;
        }

        return $this;
    }

    public function published(): self
    {
        return $this
            ->andWhere('.status = 1')
            ->andWhere('.publishedAt <= :now')
            ->setParameter(':now', (new \DateTime('now'))->format('Y-m-d H:i:s'))
        ;
    }

    protected function filterHandler(string $name, $value)
    {
        if ('category' === $name) {
            $this->inCategory($value);
        }
    }

    public function search(?string $keywords, ?string $tag)
    {
        if ($keywords) {
            $conn = $this->repository->getEm()->getConnection();

            $query = $conn->prepare(
                'SELECT
                    post.id,
                    post.title,
                    MATCH(post.title) AGAINST(:search) AS MATCH_TITLE,
                    MATCH(post.content) AGAINST(:search) AS MATCH_CONTENT
                FROM post
                WHERE
                    post.status = 1 AND
                    post.published_at < :date
                ORDER BY
                    MATCH_TITLE DESC,
                    MATCH_CONTENT DESC
            ');

            $statement = $query->execute([
                ':search' => $keywords,
                ':date' => (new \DateTime())->format('Y-m-d H:i:s'),
            ]);

            $results = $statement->fetchAll();
            $ids = [];

            foreach ($results as $k => $v) {
                $rate = ($v['MATCH_TITLE'] * 2) + $v['MATCH_CONTENT'];

                if ($rate >= 7) {
                    $ids[] = $v['id'];
                }
            }

            if (0 == count($ids)) {
                foreach ($results as $k => $v) {
                    $rate = ($v['MATCH_TITLE'] * 2) + $v['MATCH_CONTENT'];

                    if ($rate >= 6) {
                        $ids[] = $v['id'];
                    }
                }
            }

            if (!$ids) {
                $ids = [-1];
            }

            $this
                ->orderBy('FIELD(p.id, :ids)')
                ->andWhere('.id IN(:ids)')
                ->setParameter(':ids', $ids)
            ;
        }

        if ($tag) {
            $this
                ->andWhere('.tags LIKE :tag')
                ->setParameter(':tag', '%"'.$tag.'"%')
            ;
        }

        return $this;
    }
}
