<?php

namespace App\Services;

use App\Models\Collection;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use App\Exceptions\ApiHttpException;
use App\Libs\Api\ParsedListParams;
use Illuminate\Database\Eloquent\Builder;
use App\Services\DataService;
use App\Libs\Database\Eloquent\Collection\ContentTypeCollection;

class CollectionDataService extends DataService
{
    /**
     * Gets and filters Collections
     *
     * @param ParsedListParams $params - Filter and order data
     * @return Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function list(ParsedListParams $params): LengthAwarePaginator
    {
        /** @var Builder $query */
        $query = Collection::full()->where('status', 'published');

        //load the relationships
        $query->with([
            'city' => function ($query) {
                $query->full();
            },
            'image',
            'catalogue' => function ($catalogueQuery) {
                $catalogueQuery->full()->with([
                    'image',
                ])->select('*');
            },
        ]);
        //check if the default filters are to be applied
        $this->applyDefaultFilters($query, $params);
        $this->applyQueryParams($query, $params);
        return $query->paginate($params->itemsPerPage, ['*'], 'page', $params->pageNumber);
    }


    /**
     * Finds a single model for the Collection
     *
     * @param int $id
     * @throws ApiHttpException if the provided Collection record is not found.
     * @return Collection
     */
    public function find(int $id): Collection
    {
        $collection = Collection::full()
            ->where('status', 'published')
            ->with([
                'image',
                'exploreCollectionImage',
                'artists' => function ($query) {
                    $query->full()->with('image')->select('*');
                },
                'catalogue' => function ($catalogueQuery) {
                    $catalogueQuery->full()->with([
                        'image',
                        'blocks' => function ($blocksQ) {
                            BlockDataService::applyBlocksQuery($blocksQ);
                        }
                    ])->select('*');
                },
                'exhibitions' => function ($query) {
                    $query->full()->with([
                        'image',
                        'location' => function ($locQuery) {
                            $locQuery->full()->select('*');
                        }
                    ])->select('*');
                },
                'city' => function ($query) {
                    $query->full();
                },
                'blocks' => function ($blocksQ) {
                    BlockDataService::applyBlocksQuery($blocksQ);
                },
            ])->get()->find($id);

        if (!$collection) {
            throw new ApiHttpException(404, 'item_not_found');
        }

        return $collection;
    }


    /**
     * Applies the query params and filters
     *
     * @param Builder &$query
     * @param ParsedListParams $params
     * @return void
     */
    private function applyQueryParams(Builder $query, ParsedListParams $params): void
    {

        $orderDirection = $params->orderDirection;
        $orderBy        = $params->orderBy;
        if ($orderBy === 'name') {
            $orderBy = 'title';
        }

        //Defaults when no information is provided
        if (!isset($params->originalData['order']['by'])) {
            $orderBy = 'title';
        }
        if (!isset($params->originalData['order']['direction'])) {
            $orderDirection = 'ASC';
        }


        $query->orderBy($orderBy, $orderDirection);

        // Apply the specific Filters
        // Collection name Filter
        if (isset($params->filters['name'])) {
            $query->where('title', 'like', $params->filters['name'] . '%');
        }

        // Artist name Filter
        if (isset($params->filters['artist_name'])) {
            $artistName = $params->filters['artist_name'];
            $query->whereHas('artists', function ($query) use ($artistName) {
                $query->full()->where('title', 'like', $artistName . '%');
            });
        }

        // Artist id Filter
        if (isset($params->filters['artist_id'])) {
            $artistIds = $params->filters['artist_id'];
            $query->whereHas('artists', function ($query) use ($artistIds) {
                $query->whereIn('id', $artistIds);
            });
        }

        // City id Filter
        if (isset($params->filters['city_id'])) {
            $cityIds = $params->filters['city_id'];
            $query->whereHas('location', function ($query) use ($cityIds) {
                $query->whereIn('city_id', $cityIds);
            });
        }

        // City name Filter
        if (isset($params->filters['city_name'])) {
            $cityName = $params->filters['city_name'];
            $query->whereHas('location', function ($query) use ($cityName) {

                $query->whereHas('city', function ($query) use ($cityName) {
                    $query->full()->where('title', 'like', $cityName . '%');
                });
            });
        }

        // Highlights Filter
        if (isset($params->filters['highlights'])) {
            $query->where('highlight', $params->filters['highlights']);
        }

        // Coordinates filter

        $this->applyLocationFilters($query, $params);
    }


    /**
     * Applies the query params and filters
     *
     * @param Builder &$query
     * @param ParsedListParams $params
     * @return void
     */
    private function applyEntryScreenQueryParams(Builder $query, ParsedListParams $params): void
    {


        $this->applyLocationFilters($query, $params);
    }


    /**
     * Gets the collections for the entry screen
     * 
     * @param ParsedListParams $params
     * 
     * @return App\Libs\Database\Eloquent\Collection\ContentTypeCollection
     */
    public function getEntryScreenCollections(ParsedListParams $params): ContentTypeCollection
    {

        /** @var Builder $query */
        $query = Collection::full();

        $this->applyEntryScreenQueryParams($query, $params);
        $query->with([
            'image'
        ])->where('highlight', 1)->where('status', 'published')
            ->orderBy('title', 'ASC');

        return $query->get();
    }
}
