<?php

declare(strict_types=1);

namespace App\Application\Api\Images;

use App\Domain\Media\ImageRepository;
use App\Domain\Media\ImageSlotRepository;
use App\Framework\Attributes\Route;
use App\Framework\Exception\ErrorCode;
use App\Framework\Http\Exception\NotFound;
use App\Framework\Http\HttpRequest;
use App\Framework\Http\Method;
use App\Framework\Http\Responses\JsonResponse;
use App\Framework\Http\Status;

final readonly class ImageSlotController
{
    public function __construct(
        private ImageSlotRepository $slotRepository,
        private ImageRepository $imageRepository
    ) {
    }

    #[Route(path: '/api/image-slots', method: Method::GET)]
    public function getSlots(): JsonResponse
    {
        $slots = $this->slotRepository->findAllWithImages();

        return new JsonResponse([
            'slots' => array_map(fn ($slot) => [
                'id' => $slot->id,
                'slot_name' => $slot->slotName,
                'image' => $slot->image ? [
                    'ulid' => $slot->image->ulid,
                    'filename' => $slot->image->filename,
                    'url' => '/media/images/' . $slot->image->path,
                    'alt_text' => $slot->image->altText,
                    'width' => $slot->image->width,
                    'height' => $slot->image->height,
                    'mime_type' => $slot->image->mimeType,
                ] : null,
            ], $slots),
        ]);
    }

    #[Route(path: '/api/image-slots/{id}', method: Method::GET)]
    public function getSlot(int $id): JsonResponse
    {
        try {
            $slot = $this->slotRepository->findByIdWithImage((string) $id);
        } catch (\RuntimeException $e) {
            throw NotFound::create(
                ErrorCode::ENTITY_NOT_FOUND,
                $e->getMessage()
            )->withData(['slot_id' => $id]);
        }

        return new JsonResponse([
            'id' => $slot->id,
            'slot_name' => $slot->slotName,
            'image' => $slot->image ? [
                'ulid' => $slot->image->ulid,
                'filename' => $slot->image->filename,
                'url' => '/media/images/' . $slot->image->path,
                'alt_text' => $slot->image->altText,
                'width' => $slot->image->width,
                'height' => $slot->image->height,
                'mime_type' => $slot->image->mimeType,
            ] : null,
        ]);
    }

    #[Route(path: '/api/image-slots/{id}/image', method: Method::PUT)]
    public function assignImage(int $id, HttpRequest $request): JsonResponse
    {
        try {
            $slot = $this->slotRepository->findById((string) $id);
        } catch (\RuntimeException $e) {
            throw NotFound::create(
                ErrorCode::ENTITY_NOT_FOUND,
                $e->getMessage()
            )->withData(['slot_id' => $id]);
        }

        $data = $request->parsedBody->toArray();
        $imageUlid = $data['image_ulid'] ?? null;

        if (! $imageUlid) {
            return new JsonResponse(['error' => 'image_ulid is required'], Status::BAD_REQUEST);
        }

        $image = $this->imageRepository->findByUlid($imageUlid);

        if (! $image) {
            throw NotFound::create(
                ErrorCode::ENTITY_NOT_FOUND,
                "Image with ULID {$imageUlid} not found"
            )->withData(['image_ulid' => $imageUlid]);
        }

        // Update slot with new image
        $this->slotRepository->updateImageId((string) $id, $imageUlid);

        return new JsonResponse([
            'success' => true,
            'slot' => [
                'id' => $slot->id,
                'slot_name' => $slot->slotName,
                'image_ulid' => $imageUlid,
            ],
        ]);
    }

    #[Route(path: '/api/image-slots/{id}/image', method: Method::DELETE)]
    public function removeImage(int $id): JsonResponse
    {
        try {
            $slot = $this->slotRepository->findById((string) $id);
        } catch (\RuntimeException $e) {
            throw NotFound::create(
                ErrorCode::ENTITY_NOT_FOUND,
                $e->getMessage()
            )->withData(['slot_id' => $id]);
        }

        // Remove image from slot
        $this->slotRepository->updateImageId((string) $id, '');

        return new JsonResponse([
            'success' => true,
            'message' => 'Image removed from slot',
        ]);
    }
}
