<?php

declare(strict_types=1);

namespace App\Controller;

use App\Repository\AuditLogRepository;
use App\Repository\ProfileRepository;
use DateTimeInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;

final class ActivityLogController extends AbstractController
{
    public function __construct(
        private readonly AuditLogRepository $auditLogs,
        private readonly ProfileRepository $profiles,
    ) {}

    #[Route('/api/activity-logs', name: 'api_activity_logs', methods: ['GET'])]
    public function __invoke(Request $request): JsonResponse
    {
        $this->denyAccessUnlessGranted('ROLE_VIEWER');

        $page         = max(1, $request->query->getInt('page', 1));
        $itemsPerPage = min(100, max(1, $request->query->getInt('itemsPerPage', 30)));

        $filters = [];
        if ($entityType = $request->query->get('entityType')) {
            $filters['entityType'] = $entityType;
        }
        if ($action = $request->query->get('action')) {
            $filters['action'] = $action;
        }

        $result = $this->auditLogs->findAllPaginated($page, $itemsPerPage, $filters);

        $actorIds = array_values(array_unique(array_filter(array_map(
            static fn ($log) => $log->getActorProfileId(),
            $result['items'],
        ))));

        $actorMap = [];
        if ([] !== $actorIds) {
            $profiles = $this->profiles->findBy(['id' => $actorIds]);
            foreach ($profiles as $profile) {
                $label = trim(sprintf('%s %s', $profile->getFirstName(), $profile->getLastName()));
                if ('' === $label) {
                    $label = $profile->getEmail() ?? $profile->getId();
                }
                $actorMap[$profile->getId()] = $label;
            }
        }

        $items = array_map(
            static function ($log) use ($actorMap) {
                $actorId  = $log->getActorProfileId();
                $snapshot = $log->getSnapshot();

                return [
                    'id'         => $log->getId(),
                    'entityType' => $log->getEntityType(),
                    'entityId'   => $log->getEntityId(),
                    'entityName' => $snapshot['name'] ?? null,
                    'entityRef'  => $snapshot['reference'] ?? null,
                    'action'     => $log->getAction(),
                    'createdAt'  => $log->getCreatedAt()->format(DateTimeInterface::ATOM),
                    'actor'      => $actorId
                        ? [
                            'id'    => $actorId,
                            'label' => $actorMap[$actorId] ?? $actorId,
                        ]
                        : null,
                    'diff'     => $log->getDiff(),
                    'snapshot' => $snapshot,
                ];
            },
            $result['items'],
        );

        return new JsonResponse([
            'items'        => array_values($items),
            'total'        => $result['total'],
            'page'         => $page,
            'itemsPerPage' => $itemsPerPage,
        ]);
    }
}
