<?php

namespace App\Domains\Catalog\Services;

use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\FeaturedGroup;
use App\Domains\Catalog\Resources\CatalogFeaturedItemResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;

class FeaturedGroupService
{
    private const ITEMS_PER_PAGE = 12;

    /** @return array<array-key, mixed> */
    public function __construct(
        private readonly CatalogItemAllowanceService $allowances,
    ) {}

    public function itemsResponse(FeaturedGroup $featuredGroup, int $page, ?int $userId = null): array
    {
        if ($featuredGroup->group_layout !== GroupLayout::Paginated) {
            $query = $this->itemsQuery($featuredGroup);

            if ($featuredGroup->group_layout === GroupLayout::Single) {
                $query->limit(1);
            }

            $items = $query->get();
            $this->attachGroup($items, $featuredGroup);
            $this->allowances->attach($items, $userId);

            return CatalogFeaturedItemResource::collection($items)->resolve();
        }

        $paginator = $this->paginateItems($featuredGroup, $page);
        $this->attachGroup($paginator->getCollection(), $featuredGroup);
        $this->allowances->attach($paginator->getCollection(), $userId);

        return CatalogFeaturedItemResource::collection($paginator)
            ->response()
            ->getData(true);
    }

    /** @return Builder<CatalogItem> */
    private function itemsQuery(FeaturedGroup $featuredGroup): Builder
    {
        $query = CatalogItem::query()
            ->where('catalog_items.tenant_code', $featuredGroup->tenant_code)
            ->whereAvailable()
            ->where(function (Builder $query): void {
                $query
                    ->whereDoesntHave('category')
                    ->orWhereHas(
                        'category',
                        fn (Builder $categoryQuery): Builder => $categoryQuery
                            ->where('is_enabled', true),
                    );
            })
            ->with([
                'inventory',
                'attachments',
                'itemAttributes.attribute',
                'variants.inventory',
                'variants.attachments',
                'variants.eventDate',
                'variants.eventDates',
                'variants.definitions.itemAttribute.attribute.options',
                'bundleComponents.catalogItem',
                'bundleComponents.variant.catalogItem',
            ]);

        return match ($featuredGroup->source_type) {
            FeaturedGroupSource::Manual => $query
                ->select('catalog_items.*')
                ->join('featured_items', 'featured_items.catalog_item_id', '=', 'catalog_items.id')
                ->where('featured_items.featured_group_id', $featuredGroup->id)
                ->orderBy('featured_items.order')
                ->orderBy('featured_items.id'),
            FeaturedGroupSource::Category => $query
                ->where('catalog_items.category_id', $featuredGroup->category_id)
                ->orderBy('catalog_items.id'),
            FeaturedGroupSource::All => $query
                ->orderBy('catalog_items.group_order')
                ->orderBy('catalog_items.id'),
        };
    }

    private function paginateItems(
        FeaturedGroup $featuredGroup,
        int $page,
    ): LengthAwarePaginator {
        $paginator = $this->itemsQuery($featuredGroup)->paginate(
            perPage: self::ITEMS_PER_PAGE,
            pageName: 'page',
            page: $page,
        );

        return $paginator->withPath(route('catalog.featured-groups.items.index', [
            'tenant' => $featuredGroup->tenant_code,
            'featuredGroup' => $featuredGroup->id,
        ]));
    }

    private function attachGroup(iterable $items, FeaturedGroup $featuredGroup): void
    {
        foreach ($items as $item) {
            $item->setRelation('featuredGroup', $featuredGroup);
        }
    }
}
