<?php

declare(strict_types=1);

namespace App\Controller;

use App\Entity\Device;
use App\Entity\User;
use App\Enum\Orientation;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[Route('/api/devices')]
#[IsGranted('ROLE_USER')]
class DeviceApiController extends AbstractController
{
    #[Route('', name: 'api_devices_list', methods: ['GET'])]
    public function list(EntityManagerInterface $em): JsonResponse
    {
        /** @var User $user */
        $user = $this->getUser();
        $devices = $em->getRepository(Device::class)->findBy(['user' => $user]);

        return $this->json(array_map($this->serialize(...), $devices));
    }

    #[Route('/{id}', name: 'api_device_update', methods: ['PATCH'])]
    public function update(int $id, Request $request, EntityManagerInterface $em): JsonResponse
    {
        /** @var User $user */
        $user   = $this->getUser();
        $device = $em->getRepository(Device::class)->findOneBy(['id' => $id, 'user' => $user]);

        if (!$device) {
            return $this->json(['error' => 'Device not found'], Response::HTTP_NOT_FOUND);
        }

        $body = json_decode($request->getContent(), true) ?? [];

        if (isset($body['name'])) {
            $name = trim((string) $body['name']);
            if (empty($name)) {
                return $this->json(['error' => 'Name cannot be empty'], Response::HTTP_UNPROCESSABLE_ENTITY);
            }
            $device->setName($name);
        }

        if (isset($body['orientation'])) {
            $orientation = Orientation::tryFrom($body['orientation']);
            if (!$orientation) {
                return $this->json(['error' => 'Invalid orientation'], Response::HTTP_UNPROCESSABLE_ENTITY);
            }
            $device->setOrientation($orientation);
        }

        if (isset($body['rotationIntervalHours'])) {
            $device->setRotationIntervalHours(max(1, (int) $body['rotationIntervalHours']));
        }

        if (isset($body['uniquenessWindow'])) {
            $device->setUniquenessWindow(max(1, (int) $body['uniquenessWindow']));
        }

        $em->flush();

        return $this->json($this->serialize($device));
    }

    private function serialize(Device $d): array
    {
        return [
            'id'                   => $d->getId(),
            'mac'                  => $d->getMac(),
            'name'                 => $d->getName(),
            'orientation'          => $d->getOrientation()->value,
            'rotationIntervalHours' => $d->getRotationIntervalHours(),
            'uniquenessWindow'     => $d->getUniquenessWindow(),
            'linkedAt'             => $d->getLinkedAt()->format(\DateTimeInterface::ATOM),
        ];
    }
}
