<?php

namespace App\Modules\Platform\Geography\Repositories;

use App\Modules\Platform\Geography\Models\GeoCity;
use App\Support\GeoTenantScope;
use App\Support\LocalizedName;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;

class GeoCityRepository
{
    /**
     * @return list<array{value: string, label: string}>
     */
    public function searchForLookup(
        int $tenantId,
        string $query,
        int $limit,
        ?int $regionId,
        ?int $onlyId = null,
    ): array {
        if ($onlyId === null && ($regionId === null || $regionId <= 0)) {
            return [];
        }

        $builder = GeoCity::query()
            ->where('is_active', true)
            ->orderBy('sort_order')
            ->orderBy('id');

        GeoTenantScope::apply($builder, $tenantId);

        if ($regionId !== null && $regionId > 0) {
            $builder->where('region_id', $regionId);
        }

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

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

    public function paginateForTenant(
        int $tenantId,
        ?int $countryId,
        ?int $regionId,
        int $perPage = 25,
    ): LengthAwarePaginator {
        $builder = GeoCity::query()
            ->with('region.country')
            ->orderBy('sort_order')
            ->orderBy('id');

        GeoTenantScope::apply($builder, $tenantId);

        if ($regionId !== null && $regionId > 0) {
            $builder->where('region_id', $regionId);
        } elseif ($countryId !== null && $countryId > 0) {
            $builder->whereHas('region', fn ($q) => $q->where('country_id', $countryId));
        }

        return $builder->paginate($perPage)->withQueryString();
    }

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

    /**
     * @param  Collection<int, GeoCity>  $rows
     * @return list<array{value: string, label: string}>
     */
    private function mapRows(Collection $rows): array
    {
        $options = [];
        foreach ($rows as $row) {
            $options[] = [
                'value' => (string) $row->id,
                'label' => LocalizedName::fromModel($row),
            ];
        }

        return $options;
    }
}
