<?php

namespace Opentalent\OtCore\Domain\Repository;

use Exception;
use Opentalent\OtCore\Domain\Model\Event;
use Opentalent\OtCore\Exception\ApiRequestException;

class EventRepository extends BaseApiRepository
{
    const URI_TRAILING_PART = '/api/public/events';
    const HYDRA_TYPE = 'PortailEvent';

    /**
     * Get the event matching the given id
     *
     * @param int $id The id of the event
     * @return object Event
     * @throws ApiRequestException
     */
    public function findById(int $id)
    {
        $params = ["filter[where][id]" => $id];
        return $this->getApiFirstRecord($params);
    }

    /**
     * Get the events of the organization
     *
     * @param int $organizationId The id of the organization
     * @param null $fromDate Only return events with ending date posterior or equal to this date (leave null for disable the filter)
     * @param null $toDate Only return events with starting date anterior or equal to this date (leave null for disable the filter)
     * @param int $limit Limit the number of results returned (-1 to disable the limitation)
     * @param int $page
     * @return ApiPagedCollection Events
     * @throws ApiRequestException
     */
    public function findByOrganizationId(int $organizationId,
                                         $fromDate = null,
                                         $toDate = null,
                                         $limit = -1,
                                         $page = 1) {
        $params = [];
        $params['organizationId'] = $organizationId;
        $params['page'] = $page;

        if ($limit > 0) {
            $params['itemsPerPage'] = $limit;
        }
        if ($fromDate !== null) {
            // Inutile a priori: la view de l'API s'en occupe déjà en amont
            $params['filter[where][datetimeEnd][gte]'] = $fromDate->format('c');
        }
        if ($toDate !== null) {
            $params['filter[where][datetimeEnd][lte]'] = $toDate->format('c');
        }
        $params['filter[order][0][datetimeStart]'] = 'ASC';

        return $this->getApiRecords($params);
    }

    /**
     * Get the events of the organization's parents
     *
     * @param int $organizationId The id of the organization
     * @param null $fromDate Only return events with ending date posterior or equal to this date (leave null for disable the filter)
     * @param null $toDate Only return events with starting date anterior or equal to this date (leave null for disable the filter)
     * @param int $limit Limit the number of results returned (-1 to disable the limitation)
     * @param int $page
     * @return ApiPagedCollection Events
     * @throws ApiRequestException
     */
    public function findParentsByOrganizationId(int $organizationId,
                                                $fromDate = null,
                                                $toDate = null,
                                                $limit = -1,
                                                $page = 1) {
        $params = [];
        $params['organizationId'] = $organizationId;
        $params['page'] = $page;

        if ($limit > 0) {
            $params['itemsPerPage'] = $limit;
        }
        if ($fromDate !== null) {
            // Inutile a priori: la view de l'API s'en occupe déjà en amont
            $params['filter[where][datetimeEnd][gte]'] = $fromDate->format('c');
        }
        if ($toDate !== null) {
            $params['filter[where][datetimeEnd][lte]'] = $toDate->format('c');
        }
        $params['filter[order][0][datetimeStart]'] = 'ASC';

        $params['parent'] = '1';

        return $this->getApiRecords($params);
    }

    /**
     * Get the events of the organization's parents
     *
     * @param int $organizationId The id of the organization
     * @param \Datetime|null $fromDate Only return events with ending date posterior or equal to this date (leave null for disable the filter)
     * @param \Datetime|null $toDate Only return events with starting date anterior or equal to this date (leave null for disable the filter)
     * @param int $limit Limit the number of results returned (-1 to disable the limitation)
     * @return ApiPagedCollection Events
     * @throws ApiRequestException
     */
    public function findChildrenByOrganizationId(int $organizationId, $fromDate = null, $toDate = null, $limit = -1) {
        $params = [];
        $params['organizationId'] = $organizationId;

        if ($limit > 0) {
            $params['itemsPerPage'] = $limit;
        }
        if ($fromDate !== null) {
            // Inutile a priori: la view de l'API s'en occupe déjà en amont
            $params['filter[where][datetimeEnd][gte]'] = $fromDate->format('c');
        }
        if ($toDate !== null) {
            $params['filter[where][datetimeEnd][lte]'] = $toDate->format('c');
        }
        $params['filter[order][0][datetimeStart]'] = 'ASC';

        $params['children'] = '1';

        return $this->getApiRecords($params);
    }

    /**
     * Get the events of the organization
     *
     * @param int $organizationId The id of the organization
     * @param array $searchParams Search arguments
     * @return ApiPagedCollection                        Events
     * @throws ApiRequestException
     * @throws Exception
     */
    public function searchBy(int $organizationId, $searchParams = []) {
        $params = [];
        $params['organizationId'] = $organizationId;
        $params['filter[order][0][datetimeStart]'] = 'ASC';
        $params = array_merge($params, $searchParams);

        return $this->getApiRecords($params);
    }

    /**
     * Returns an Event object from an Api record
     *
     * @param array $record A record as returned by $this->getApiRecords
     * @return Event|null
     * @throws Exception
     */
    protected function memberToObject(array $record): ?Event {
        if ($record['@type'] != $this::HYDRA_TYPE) {
            return null;
        }
        $event = new Event();
        $a = explode('/', $record['@id']);
        $event->setId(end($a));
        if ($record['organizationId'] !== null) {
            $event->setOrganizationId($record['organizationId']);
        }
        $event->setSubdomain($record['subDomain'] ?? '');
        $event->setName($record['name']);
        $event->setDescription($record['description']);
        $event->setUrl($record['url']);
        $event->setRule($record['rule']);
        $dateStart = new \DateTime($record['datetimeStart']);
        $dateStart->setTimezone(new \DateTimeZone('Europe/Paris'));
        $event->setDatetimeStart($dateStart);
        $dateEnd = new \DateTime($record['datetimeEnd']);
        $dateEnd->setTimezone(new \DateTimeZone('Europe/Paris'));
        $event->setDatetimeEnd($dateEnd);
        $event->setDates($record['dates']);
        $event->setPlacename($record['placeName']);
        $event->setPlaceDescription($record['placeDescription']);
        $event->setPlaceFloorSize($record['placeFloorSize']);
        $event->setPlaceCapacity($record['placeCapacity']);
        $event->setCity($record['city']);
        $event->setPostalCode($record['postalCode']);
        $event->setStreetAddress($record['streetAddress']);
        $event->setLongitude($record['longitude']);
        $event->setLatitude($record['latitude']);
        $event->setRoomName($record['roomName']);
        $event->setRoomDescription($record['roomDescription']);
        $event->setRoomLocalisation($record['roomLocalisation']);
        $event->setRoomCapacity($record['roomCapacity']);
        $event->setRoomFloorSize($record['roomFloorSize']);
        $event->setZupId($record['zupId']);
        $event->setDeepLink($record['deepLink']);
        $event->setImage($record['image']);
        $event->setPriceMini($record['priceMini']);
        $event->setMeetingSchedule($record['meetingSchedule']);
        $event->setApi($record['api']);
        $event->setParentName($record['parentName']);
        $event->setParentSubdomain($record['parentSubDomain']);
        return $event;
    }
}
