<?php

namespace App\Controller\Api;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;

/**
 * @codeCoverageIgnore Requires JWT auth integration
 */
#[Route('/api/sandbox')]
class ApiSandboxController extends AbstractController
{
    use ApiAuthTrait;

    /** @var array<string, mixed>|null */
    private ?array $fixtures = null;

    public function __construct(
        #[Autowire('%kernel.project_dir%')] private string $projectDir,
        #[Autowire('%kernel.secret%')] private string $appSecret,
    ) {
    }

    #[Route('/events', name: 'app_api_sandbox_events', methods: ['GET'])]
    public function events(Request $request, EntityManagerInterface $em): JsonResponse
    {
        $auth = $this->authenticateRequest($request, $em, $this->appSecret);
        if ($auth instanceof JsonResponse) {
            return $auth;
        }

        $fixtures = $this->loadFixtures();

        return $this->success($fixtures['events'] ?? []);
    }

    #[Route('/events/{id}', name: 'app_api_sandbox_event', requirements: ['id' => '\d+'], methods: ['GET'])]
    public function event(int $id, Request $request, EntityManagerInterface $em): JsonResponse
    {
        $auth = $this->authenticateRequest($request, $em, $this->appSecret);
        if ($auth instanceof JsonResponse) {
            return $auth;
        }

        $fixtures = $this->loadFixtures();
        foreach ($fixtures['events'] ?? [] as $event) {
            if ($event['id'] === $id) {
                return $this->success($event);
            }
        }

        return $this->error('Evenement introuvable.', 404);
    }

    #[Route('/events/{id}/categories', name: 'app_api_sandbox_categories', requirements: ['id' => '\d+'], methods: ['GET'])]
    public function categories(int $id, Request $request, EntityManagerInterface $em): JsonResponse
    {
        $auth = $this->authenticateRequest($request, $em, $this->appSecret);
        if ($auth instanceof JsonResponse) {
            return $auth;
        }

        $fixtures = $this->loadFixtures();

        return $this->success($fixtures['categories'][(string) $id] ?? []);
    }

    #[Route('/categories/{id}/billets', name: 'app_api_sandbox_billets', requirements: ['id' => '\d+'], methods: ['GET'])]
    public function billets(int $id, Request $request, EntityManagerInterface $em): JsonResponse
    {
        $auth = $this->authenticateRequest($request, $em, $this->appSecret);
        if ($auth instanceof JsonResponse) {
            return $auth;
        }

        $fixtures = $this->loadFixtures();

        return $this->success($fixtures['billets'][(string) $id] ?? []);
    }

    #[Route('/billets/{id}', name: 'app_api_sandbox_billet', requirements: ['id' => '\d+'], methods: ['GET'])]
    public function billet(int $id, Request $request, EntityManagerInterface $em): JsonResponse
    {
        $auth = $this->authenticateRequest($request, $em, $this->appSecret);
        if ($auth instanceof JsonResponse) {
            return $auth;
        }

        $fixtures = $this->loadFixtures();
        $detail = $fixtures['billetDetails'][(string) $id] ?? null;

        if (!$detail) {
            return $this->error('Billet introuvable.', 404);
        }

        return $this->success($detail);
    }

    #[Route('/scan', name: 'app_api_sandbox_scan', methods: ['POST'])]
    public function scan(Request $request, EntityManagerInterface $em): JsonResponse
    {
        $auth = $this->authenticateRequest($request, $em, $this->appSecret);
        if ($auth instanceof JsonResponse) {
            return $auth;
        }

        $data = json_decode($request->getContent(), true);
        $reference = $data['reference'] ?? '';

        if ('' === $reference) {
            return $this->error('Reference requise.', 400);
        }

        $fixtures = $this->loadFixtures();
        $result = $fixtures['scan'][$reference] ?? null;

        return $result
            ? $this->success(array_diff_key($result, ['_comment' => true]))
            : $this->error('Billet introuvable.', 404);
    }

    /**
     * @return array<string, mixed>
     */
    private function loadFixtures(): array
    {
        if (null === $this->fixtures) {
            $path = $this->projectDir.'/data/sandbox/fixtures.json';
            $this->fixtures = json_decode((string) file_get_contents($path), true) ?? [];
        }

        return $this->fixtures;
    }
}
