<?php

namespace App\Modules\Platform\Geography\Services;

use App\Modules\Platform\Geography\Models\GeoCity;
use App\Modules\Platform\Geography\Models\GeoRegion;
use App\Modules\Platform\Geography\Repositories\GeoCityRepository;
use App\Modules\Platform\Geography\Repositories\GeoCountryRepository;
use App\Modules\Platform\Geography\Repositories\GeoRegionRepository;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

final class GeographyCatalogService
{
    public function __construct(
        private readonly GeoCountryRepository $countries,
        private readonly GeoRegionRepository $regions,
        private readonly GeoCityRepository $cities,
    ) {}

    public function paginateCountries(int $perPage = 25): LengthAwarePaginator
    {
        return $this->countries->paginateForAdmin($perPage);
    }

    public function paginateRegions(int $tenantId, ?int $countryId, int $perPage = 25): LengthAwarePaginator
    {
        return $this->regions->paginateForTenant($tenantId, $countryId, $perPage);
    }

    public function paginateCities(int $tenantId, ?int $countryId, ?int $regionId, int $perPage = 25): LengthAwarePaginator
    {
        return $this->cities->paginateForTenant($tenantId, $countryId, $regionId, $perPage);
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function createRegion(int $tenantId, array $data): GeoRegion
    {
        return $this->regions->createTenantRegion($tenantId, $this->regionPayload($data));
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function updateRegion(GeoRegion $region, array $data): GeoRegion
    {
        $region->update($this->regionPayload($data));

        return $region->fresh(['country']);
    }

    public function deactivateRegion(GeoRegion $region): void
    {
        $region->update(['is_active' => false]);
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function createCity(int $tenantId, array $data): GeoCity
    {
        return $this->cities->createTenantCity($tenantId, $this->cityPayload($data));
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function updateCity(GeoCity $city, array $data): GeoCity
    {
        $city->update($this->cityPayload($data));

        return $city->fresh(['region.country']);
    }

    public function deactivateCity(GeoCity $city): void
    {
        $city->update(['is_active' => false]);
    }

    public function assertTenantOwned(GeoRegion|GeoCity $record, int $tenantId): void
    {
        if ((int) $record->tenant_id !== $tenantId) {
            abort(403);
        }
    }

    /**
     * @param  array<string, mixed>  $data
     * @return array<string, mixed>
     */
    private function regionPayload(array $data): array
    {
        return [
            'country_id' => (int) $data['country_id'],
            'name' => [
                'en' => (string) $data['name_en'],
                'ar' => (string) ($data['name_ar'] ?? $data['name_en']),
            ],
            'sort_order' => (int) ($data['sort_order'] ?? 0),
            'is_active' => (bool) ($data['is_active'] ?? true),
        ];
    }

    /**
     * @param  array<string, mixed>  $data
     * @return array<string, mixed>
     */
    private function cityPayload(array $data): array
    {
        return [
            'region_id' => (int) $data['region_id'],
            'name' => [
                'en' => (string) $data['name_en'],
                'ar' => (string) ($data['name_ar'] ?? $data['name_en']),
            ],
            'sort_order' => (int) ($data['sort_order'] ?? 0),
            'is_active' => (bool) ($data['is_active'] ?? true),
        ];
    }
}
