<?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\Api\Point\Request;

use InPost\International\Api\Point\Model\Coordinates;
use InPost\International\Api\Point\Model\PointCapability;
use InPost\International\Country;

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

final class PointsSearchByLocationRequest
{
    /**
     * @var int|null
     */
    private $page;

    /**
     * @var int|null
     */
    private $perPage;

    /**
     * @var string|null
     */
    private $relativePoint;

    /**
     * @var string|null
     */
    private $relativePostCode;

    /**
     * @var int|null
     */
    private $maxDistance;

    /**
     * @var Country|null
     */
    private $country;

    /**
     * @var int|null
     */
    private $limit;

    /**
     * @var PointCapability[]
     */
    private $capabilities;

    /**
     * @param PointCapability[] $capabilities
     */
    public function __construct(int $page = null, int $perPage = null, string $relativePoint = null, string $relativePostCode = null, int $maxDistance = null, Country $country = null, int $limit = null, array $capabilities = [])
    {
        $this->page = $page;
        $this->perPage = $perPage;
        $this->relativePoint = $relativePoint;
        $this->relativePostCode = $relativePostCode;
        $this->maxDistance = $maxDistance;
        $this->country = $country;
        $this->limit = $limit;
        $this->capabilities = $capabilities;
    }

    public static function byCoordinates(Coordinates $coordinates, array $capabilities = [], $limit = 1): self
    {
        return new self(
            null,
            null,
            (string) $coordinates,
            null,
            null,
            null,
            $limit,
            $capabilities
        );
    }

    public static function byPostCode(string $postCode, Country $country, array $capabilities = [], $limit = 1): self
    {
        return new self(
            null,
            null,
            null,
            $postCode,
            null,
            $country,
            $limit,
            $capabilities
        );
    }

    public function getPage(): ?int
    {
        return $this->page;
    }

    public function getPerPage(): ?int
    {
        return $this->perPage;
    }

    public function getRelativePoint(): ?string
    {
        return $this->relativePoint;
    }

    public function getRelativePostCode(): ?string
    {
        return $this->relativePostCode;
    }

    public function getMaxDistance(): ?int
    {
        return $this->maxDistance;
    }

    public function getCountry(): ?Country
    {
        return $this->country;
    }

    public function getLimit(): ?int
    {
        return $this->limit;
    }

    public function getCapabilities(): ?array
    {
        return $this->capabilities;
    }

    /**
     * @return array<string, string>
     */
    public function toQueryParameters(): array
    {
        $params = [];

        if (null !== $this->page) {
            $params['page'] = (string) $this->page;
        }

        if (null !== $this->perPage) {
            $params['perPage'] = (string) $this->perPage;
        }

        if (null !== $this->relativePoint) {
            $params['relativePoint'] = $this->relativePoint;
        }

        if (null !== $this->relativePostCode) {
            $params['relativePostCode'] = $this->relativePostCode;
        }

        if (null !== $this->maxDistance) {
            $params['maxDistance'] = (string) $this->maxDistance;
        }

        if (null !== $this->country) {
            $params['address.country'] = $this->country->value;
        }

        if (null !== $this->limit) {
            $params['limit'] = (string) $this->limit;
        }

        if ([] !== $this->capabilities) {
            $params['capabilities'] = implode(',', array_map(static function (PointCapability $capability): string {
                return $capability->value;
            }, $this->capabilities));
        }

        return $params;
    }
}
