<?php

declare(strict_types=1);

namespace App\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\ApiResource\WorkHourBulkValidation;
use App\ApiResource\WorkHourBulkValidationResult;
use App\Entity\User;
use App\Entity\WorkHour;
use App\Service\AuditLogger;
use App\Service\WorkHours\WorkHourBulkValidationExecutor;
use DateTimeImmutable;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

final readonly class WorkHourBulkValidationProcessor implements ProcessorInterface
{
    public function __construct(
        private Security $security,
        private WorkHourBulkValidationExecutor $executor,
        private AuditLogger $auditLogger,
    ) {}

    public function process(
        mixed $data,
        Operation $operation,
        array $uriVariables = [],
        array $context = []
    ): WorkHourBulkValidationResult {
        if (!$data instanceof WorkHourBulkValidation) {
            throw new BadRequestHttpException('Invalid payload.');
        }

        $user = $this->security->getUser();
        if (!$user instanceof User) {
            throw new AccessDeniedHttpException('Authentication required.');
        }

        if (!in_array('ROLE_ADMIN', $user->getRoles(), true)) {
            throw new AccessDeniedHttpException('Only admins can bulk validate work hours.');
        }

        $result = $this->executor->execute(
            user: $user,
            workDateValue: $data->workDate,
            employeeIds: $data->employeeIds,
            shouldSkip: static fn (WorkHour $workHour): bool => $workHour->isValid() === $data->isValid,
            applyUpdate: static function (WorkHour $workHour) use ($data): void {
                $workHour->setIsValid($data->isValid);
            }
        );

        if ($result->updated > 0) {
            $workDate = DateTimeImmutable::createFromFormat('Y-m-d', $data->workDate);
            $action   = $data->isValid ? 'validé' : 'dévalidé';

            $this->auditLogger->log(
                null,
                'validate',
                'work_hour',
                null,
                sprintf('Validation RH %s pour %d employé(s) le %s', $action, $result->updated, $data->workDate),
                ['employeeIds' => $data->employeeIds, 'isValid' => $data->isValid],
                $workDate ?: null,
            );
        }

        return $result;
    }
}
