<?php

namespace Containers\Dto;

readonly class ContainerListArgumentsDto
{
    public function __construct(
        public int     $page = 1,
        public int     $per_page = 20,
        public string  $sort_column = 'started_at',
        public string  $sort_direction = 'desc',
        public ?string $hostkey = null,
        public ?string $owner = null,
        public ?string $name = null,
        public ?string $image = null,
        public ?string $state = null,
        public ?string $engine = null,
        public ?array  $container_port = null,
        public ?array  $host_port = null,
        public ?array  $host_ip = null,
        public ?array  $protocol = null,
        public ?string $created_at_from = null,
        public ?string $created_at_to = null,
        public ?string $finished_at_from = null,
        public ?string $finished_at_to = null,
    ) {
    }

    public static function fromArray(array $data): self
    {
        return new self(
            page: isset($data['page']) ? max(1, (int) $data['page']) : 1,
            per_page: isset($data['per_page']) ? max(1, min(100, (int) $data['per_page'])) : 20,
            sort_column: $data['sort'] ?? 'started_at',
            sort_direction: strtolower($data['order'] ?? 'desc') === 'asc' ? 'asc' : 'desc',
            hostkey: $data['hostkey'] ?? null,
            owner: $data['owner'] ?? null,
            name: $data['name'] ?? null,
            image: $data['image'] ?? null,
            state: $data['state'] ?? null,
            engine: $data['engine'] ?? null,
            container_port: self::normalizeIntList($data['container_port'] ?? null),
            host_port: self::normalizeIntList($data['host_port'] ?? null),
            host_ip: self::normalizeStringList($data['host_ip'] ?? null),
            protocol: self::normalizeStringList($data['protocol'] ?? null, strtolower: true),
            created_at_from: self::normalizeDate($data['created_at_from'] ?? null),
            created_at_to: self::normalizeDate($data['created_at_to'] ?? null),
            finished_at_from: self::normalizeDate($data['finished_at_from'] ?? null),
            finished_at_to: self::normalizeDate($data['finished_at_to'] ?? null),
        );
    }

    private static function normalizeDate(mixed $value): ?string
    {
        if ($value === null || $value === '') {
            return null;
        }
        return (string) $value;
    }

    private static function normalizeIntList(mixed $value): ?array
    {
        if ($value === null || $value === '' || $value === []) {
            return null;
        }
        $items = is_array($value) ? $value : [$value];
        $items = array_values(array_unique(array_map(fn ($v) => (int) $v, $items)));
        return $items === [] ? null : $items;
    }

    private static function normalizeStringList(mixed $value, bool $strtolower = false): ?array
    {
        if ($value === null || $value === '' || $value === []) {
            return null;
        }
        $items = is_array($value) ? $value : [$value];
        $items = array_map(fn ($v) => $strtolower ? strtolower((string) $v) : (string) $v, $items);
        $items = array_values(array_unique(array_filter($items, fn ($v) => $v !== '')));
        return $items === [] ? null : $items;
    }

    public function skip(): int
    {
        return ($this->page - 1) * $this->per_page;
    }
}
