<?php

declare(strict_types=1);

namespace App\Application\Api\Images;

use App\Domain\Media\Image;
use App\Framework\Attributes\Route;
use App\Framework\Http\HttpRequest;
use App\Framework\Http\Method;
use App\Framework\Http\Responses\JsonResponse;
use App\Framework\Http\Status;
use App\Framework\Pagination\PaginationService;
use App\Framework\Pagination\ValueObjects\Direction;

final readonly class ListImagesController
{
    public function __construct(
        private PaginationService $paginationService
    ) {
    }

    #[Route(path: '/api/images', method: Method::GET)]
    public function __invoke(HttpRequest $request): JsonResponse
    {
        // Parse query parameters
        $limit = $this->parseLimit($request);
        $page = $this->parsePage($request);
        $sortField = $this->parseSortField($request);
        $direction = $this->parseDirection($request);
        $cursor = $this->parseCursor($request);

        // Create pagination request
        if ($cursor !== null) {
            // Cursor-based pagination
            $paginationRequest = $this->paginationService->cursorRequest(
                limit: $limit,
                cursorValue: $cursor,
                sortField: $sortField,
                direction: $direction
            );
        } else {
            // Offset-based pagination
            $offset = ($page - 1) * $limit;
            $paginationRequest = $this->paginationService->offsetRequest(
                limit: $limit,
                offset: $offset,
                sortField: $sortField,
                direction: $direction
            );
        }

        // Get paginated results
        $paginator = $this->paginationService->forEntity(Image::class);
        $paginationResponse = $paginator->paginate($paginationRequest);

        // Transform images to API format
        $transformedData = array_map([$this, 'transformImage'], $paginationResponse->data);

        // Create response with transformed data
        $responseData = [
            'data' => $transformedData,
            'meta' => $paginationResponse->meta->toArray(),
        ];

        return new JsonResponse($responseData, Status::OK);
    }

    /**
     * Parse limit parameter with validation
     */
    private function parseLimit(HttpRequest $request): int
    {
        $limit = $request->query->getInt('limit', 20);

        // Validate limit bounds
        if ($limit < 1) {
            $limit = 1;
        } elseif ($limit > 100) {
            $limit = 100;
        }

        return $limit;
    }

    /**
     * Parse page parameter with validation
     */
    private function parsePage(HttpRequest $request): int
    {
        $page = $request->query->getInt('page', 1);

        return max(1, $page);
    }

    /**
     * Parse sort field parameter
     */
    private function parseSortField(HttpRequest $request): ?string
    {
        $sortField = $request->query->getString('sort');

        // Allow only specific fields for security
        $allowedFields = ['ulid', 'filename', 'width', 'height', 'fileSize'];

        if ($sortField && in_array($sortField, $allowedFields)) {
            return $sortField;
        }

        // Default sort by creation time (via ULID)
        return 'ulid';
    }

    /**
     * Parse direction parameter
     */
    private function parseDirection(HttpRequest $request): string
    {
        $direction = $request->query->getString('direction', 'desc');

        return in_array($direction, ['asc', 'desc']) ? $direction : 'desc';
    }

    /**
     * Parse cursor parameter
     */
    private function parseCursor(HttpRequest $request): ?string
    {
        return $request->query->getString('cursor');
    }

    /**
     * Transform Image entity to API representation
     */
    private function transformImage(Image $image): array
    {
        return [
            'ulid' => $image->getUlidString(),
            'filename' => $image->filename,
            'original_filename' => $image->originalFilename,
            'url' => '/images/' . $image->filename,
            'thumbnail_url' => '/images/' . str_replace('_original.', '_thumbnail.', $image->filename),
            'alt_text' => $image->altText,
            'dimensions' => [
                'width' => $image->width,
                'height' => $image->height,
                'aspect_ratio' => $image->getAspectRatio(),
                'orientation' => $image->getDimensions()->getOrientation()->value,
            ],
            'mime_type' => $image->mimeType->value,
            'file_size' => [
                'bytes' => $image->fileSize->toBytes(),
                'human_readable' => $image->getHumanReadableFileSize(),
            ],
            'hash' => $image->hash->toString(),
            'is_image' => $image->isImageFile(),
            'created_at' => $image->ulid->getDateTime()->format('c'),
            'variants' => array_map(fn ($variant) => [
                'type' => $variant->variantType,
                'width' => $variant->width,
                'height' => $variant->height,
                'path' => $variant->path,
                'url' => '/images/' . $variant->filename,
            ], $image->variants ?? []),
        ];
    }
}
