<?php

namespace App\Modules\Inventory\Repositories;

use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Support\InventoryLifecycleState;
use App\Support\Lists\ListQuery;
use App\Support\SelectOptionFormatter;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;

class WarehouseRepository
{
    /**
     * @return Collection<int, Warehouse>
     */
    public function activeOrdered(): Collection
    {
        return Warehouse::query()
            ->where('is_active', true)
            ->where('lifecycle_state', InventoryLifecycleState::Active)
            ->orderBy('code')
            ->get();
    }

    /**
     * @return Collection<int, Warehouse>
     */
    public function listWithSectionsOrdered(int $tenantId): Collection
    {
        return Warehouse::query()
            ->where('tenant_id', $tenantId)
            ->with([
                'sections' => static fn ($q) => $q->orderBy('sort_order')->orderBy('code'),
            ])
            ->orderBy('code')
            ->get();
    }

    public function paginateForIndex(int $tenantId, Request $request): LengthAwarePaginator
    {
        $query = Warehouse::query()
            ->where('tenant_id', $tenantId)
            ->with([
                'sections' => static fn ($q) => $q->orderBy('sort_order')->orderBy('code'),
            ]);

        ListQuery::applySearch($query, $request->input('q'), ['name', 'code']);
        ListQuery::applyBoolean($query, 'is_active', $request->input('is_active'));
        ListQuery::applySort(
            $query,
            $request->input('sort'),
            $request->input('dir'),
            [
                'code' => 'code',
                'name' => 'name',
                'is_active' => 'is_active',
            ],
            'code',
        );

        return ListQuery::paginate($query, $request);
    }

    public function findWithSections(int $tenantId, int $warehouseId): ?Warehouse
    {
        return Warehouse::query()
            ->where('tenant_id', $tenantId)
            ->whereKey($warehouseId)
            ->with([
                'sections' => static fn ($q) => $q->orderBy('sort_order')->orderBy('code'),
            ])
            ->first();
    }

    /**
     * @param  array<string, mixed>  $attributes
     */
    public function create(int $tenantId, array $attributes): Warehouse
    {
        return Warehouse::query()->create(array_merge(['tenant_id' => $tenantId], $attributes));
    }

    /**
     * @return list<array{value: string, label: string}>
     */
    public function searchForLookup(
        int $tenantId,
        string $query,
        int $limit = 30,
        ?int $onlyId = null,
    ): array {
        $builder = Warehouse::query()
            ->where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->orderBy('code');

        if ($onlyId !== null) {
            $builder->whereKey($onlyId);
        } else {
            if ($query !== '') {
                $builder->where(function ($q) use ($query): void {
                    $q->where('name', 'like', '%'.$query.'%')
                        ->orWhere('code', 'like', '%'.$query.'%');
                });
            }
            $builder->limit($limit);
        }

        return SelectOptionFormatter::mapRows(
            $builder->get(['id', 'name', 'code']),
            'name',
            'code',
        );
    }
}
