<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Checkout\View\Model;

use InPost\International\Delivery\Point\RelativePointInterface;
use PrestaShop\PrestaShop\Core\Localization\LocaleInterface;

if (!defined('_PS_VERSION_')) {
    exit;
}

/**
 * @implements \ArrayAccess<string, string>
 */
final class ClosestPointView implements \ArrayAccess, \JsonSerializable
{
    /**
     * @var RelativePointInterface
     */
    private $point;

    /**
     * @var LocaleInterface|null
     */
    private $locale;

    public function __construct(RelativePointInterface $point, LocaleInterface $locale = null)
    {
        $this->point = $point;
        $this->locale = $locale;
    }

    public function offsetExists($offset): bool
    {
        return in_array($offset, [
            'name',
            'formatted_address',
            'distance',
        ]);
    }

    public function offsetGet($offset): string
    {
        switch ($offset) {
            case 'name':
                return $this->point->getId();
            case 'formatted_address':
                return (string) $this->point->getAddress();
            case 'distance':
                return $this->getDistance();
            default:
                throw new \OutOfRangeException(sprintf('Undefined index "%s".', $offset));
        }
    }

    public function offsetSet($offset, $value): void
    {
        throw new \BadMethodCallException('Not supported.');
    }

    public function offsetUnset($offset): void
    {
        throw new \BadMethodCallException('Not supported.');
    }

    /**
     * @return array<string, string>
     */
    public function jsonSerialize(): array
    {
        return [
            'name' => $this->point->getId(),
            'formatted_address' => (string) $this->point->getAddress(),
            'distance' => $this->getDistance(),
        ];
    }

    private function getDistance(): string
    {
        $distance = $this->point->getDistance();
        $unit = 'm';

        if ($distance > 1000) {
            $unit = 'km';
            $distance /= 1000.;
        }

        if (null === $this->locale) {
            return sprintf('%.2f %s', $distance, $unit);
        }

        return $this->locale->formatNumber($distance) . ' ' . $unit;
    }
}
