<?php
namespace Newland\Toubiz\Sync\Neos\Domain\Repository;

/*
 * This file is part of the "toubiz-sync-neos" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Doctrine\ORM\QueryBuilder;
use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Api\ObjectAdapter\Concern\TransportationFacilityConstants;
use Newland\Toubiz\Sync\Neos\Command\OrphanFinder;
use Newland\Toubiz\Sync\Neos\Domain\Filter\FilterInterface;
use Newland\Toubiz\Sync\Neos\Domain\Filter\TransportationFacilityFilter;
use Newland\Toubiz\Sync\Neos\Domain\Model\TransportationFacility;

/**
 * Transportation facility repository.
 *
 * @Flow\Scope("singleton")
 *
 * @method TransportationFacility|null findOneByOriginalId(string $originalId)
 */
class TransportationFacilityRepository extends AbstractRepository implements OrphanFinder
{

    /**
     * Calculates statistics for region.
     *
     * @param array $regions
     * @return array
     */
    public function getStatistics(array $regions = [])
    {
        $query = $this->createQueryBuilder('transportationFacility');
        $query->leftJoin('transportationFacility.regions', 'region');

        $constraint = '';
        if (!empty($regions)) {
            $regionIds = [];
            foreach ($regions as $region) {
                $regionIds[] = $region->getPersistenceObjectIdentifier();
            }
            $query->setParameter('regionIds', $regionIds);
            $constraint = 'AND region IN(:regionIds)';
        }

        $query->select('
            SUM (
                CASE WHEN
                    transportationFacility.type IN(
                        ' . TransportationFacilityConstants::TYPE_SKI_LIFT . ',
                        ' . TransportationFacilityConstants::TYPE_4_SEATER_CHAIRLIFT . ',
                        ' . TransportationFacilityConstants::TYPE_6_SEATER_CHAIRLIFT . ',
                        ' . TransportationFacilityConstants::TYPE_GONDOLA . '
                    )
                    AND transportationFacility.status = ' . TransportationFacilityConstants::STATUS_OPEN . '
                    ' . $constraint . '
                THEN 1 ELSE 0 END
            ) AS lifts_open,
            SUM (
                CASE WHEN
                    transportationFacility.type IN(
                        ' . TransportationFacilityConstants::TYPE_SKI_LIFT . ',
                        ' . TransportationFacilityConstants::TYPE_4_SEATER_CHAIRLIFT . ',
                        ' . TransportationFacilityConstants::TYPE_6_SEATER_CHAIRLIFT . ',
                        ' . TransportationFacilityConstants::TYPE_GONDOLA . '
                    )
                    ' . $constraint . '
                THEN 1 ELSE 0 END
            ) AS lifts_total,

            SUM (
                CASE WHEN
                    transportationFacility.type IN(
                        ' . TransportationFacilityConstants::TYPE_REVERSIBLE_AERIAL_TRAM . ',
                        ' . TransportationFacilityConstants::TYPE_COGWHEEL_RAILWAY . '
                    )
                    AND transportationFacility.status = ' . TransportationFacilityConstants::STATUS_OPEN . '
                    ' . $constraint . '
                THEN 1 ELSE 0 END
            ) AS mountain_railways_open,
            SUM (
                CASE WHEN
                    transportationFacility.type IN(
                        ' . TransportationFacilityConstants::TYPE_REVERSIBLE_AERIAL_TRAM . ',
                        ' . TransportationFacilityConstants::TYPE_COGWHEEL_RAILWAY . '
                    )
                    ' . $constraint . '
                THEN 1 ELSE 0 END
            ) AS mountain_railways_total
        ');
        return $query->getQuery()->execute()[0];
    }

    /**
     * @return iterable
     */
    public function findOrphans()
    {
        $query = $this->createQueryBuilder('facility');

        return $query->join('facility.regions', 'regions')
            ->andWhere($query->expr()->isNull('regions.Persistence_Object_Identifier'))
            ->getQuery()
            ->execute();
    }

    /**
     * @param TransportationFacilityFilter $filter
     * @param QueryBuilder $query
     * @return QueryBuilder
     */
    protected function applyFilter(FilterInterface $filter, QueryBuilder $query): QueryBuilder
    {
        $this->applyBasicFilter($filter, $query);
        $query->leftJoin('transportationFacility.regions', 'region');

        $regions = $filter->getRegions();
        if (!empty($regions)) {
            $query->andWhere($query->expr()->in('region', $regions));
        }

        $types = $filter->getTypes();
        if (!empty($types)) {
            $query->andWhere($query->expr()->in('transportationFacility.type', $types));
        }

        return $query;
    }
}
