<?php

declare(strict_types=1);

namespace ImovelZapAi\Properties\Application\Data;

final readonly class PropertyImagesInput
{
    /**
     * @param  list<\Illuminate\Http\UploadedFile>  $newFiles
     * @param  list<string|null>  $newCaptions
     * @param  list<int>  $newOrders
     * @param  array<string, string|null>  $existingCaptions
     * @param  array<string, int>  $existingOrders
     * @param  list<string>  $deleteImageIds
     */
    public function __construct(
        public array $newFiles = [],
        public array $newCaptions = [],
        public array $newOrders = [],
        public ?int $newCoverIndex = null,
        public array $existingCaptions = [],
        public array $existingOrders = [],
        public ?string $coverImageId = null,
        public array $deleteImageIds = [],
    ) {}

    /**
     * @param  array<string, mixed>  $validated
     * @param  list<\Illuminate\Http\UploadedFile>  $files
     */
    public static function fromRequest(array $validated, array $files): self
    {
        $existingCaptions = [];
        $existingOrders = [];
        $newCaptions = [];
        $newOrders = [];

        foreach ($validated['image_captions'] ?? [] as $key => $caption) {
            if (self::isUuidKey($key)) {
                $existingCaptions[(string) $key] = is_string($caption) ? $caption : null;
            } elseif (self::isNumericKey($key)) {
                $newCaptions[] = is_string($caption) ? $caption : null;
            }
        }

        foreach ($validated['image_orders'] ?? [] as $key => $order) {
            if (self::isUuidKey($key) && is_numeric($order)) {
                $existingOrders[(string) $key] = (int) $order;
            } elseif (self::isNumericKey($key) && is_numeric($order)) {
                $newOrders[] = (int) $order;
            }
        }

        foreach ($validated['new_image_captions'] ?? [] as $caption) {
            $newCaptions[] = is_string($caption) ? $caption : null;
        }

        foreach ($validated['new_image_orders'] ?? [] as $order) {
            if (is_numeric($order)) {
                $newOrders[] = (int) $order;
            }
        }

        $coverIndex = isset($validated['cover_index']) && is_numeric($validated['cover_index'])
            ? (int) $validated['cover_index']
            : (isset($validated['new_cover_index']) && is_numeric($validated['new_cover_index'])
                ? (int) $validated['new_cover_index']
                : null);

        return new self(
            newFiles: $files,
            newCaptions: $newCaptions,
            newOrders: $newOrders,
            newCoverIndex: $coverIndex,
            existingCaptions: $existingCaptions,
            existingOrders: $existingOrders,
            coverImageId: isset($validated['cover_image_id']) ? (string) $validated['cover_image_id'] : null,
            deleteImageIds: array_values($validated['delete_images'] ?? []),
        );
    }

    private static function isUuidKey(mixed $key): bool
    {
        return is_string($key) && preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $key) === 1;
    }

    private static function isNumericKey(mixed $key): bool
    {
        return is_int($key) || (is_string($key) && ctype_digit($key));
    }
}
