<?php

namespace GriffinForms\Frontend\Security;

use GriffinForms\Frontend\Security\Guards\GuardInterface;
use GriffinForms\Frontend\Security\Guards\AvailabilityWindowGuard;
use GriffinForms\Frontend\Security\Guards\LimitEntriesGuard;
use GriffinForms\Frontend\Security\Guards\SubmissionEditWindowGuard;
use GriffinForms\Frontend\Security\Guards\SubmissionEditAccessGuard;

class FormGuardManager
{
    /**
     * @var array<int,GuardInterface>
     */
    protected $guards = [];

    /**
     * @param array<int,GuardInterface|string> $guards
     */
    public function __construct(array $guards = [])
    {
        if (empty($guards)) {
            $this->registerGuard(new AvailabilityWindowGuard());
            $this->registerGuard(new LimitEntriesGuard());
            $this->registerGuard(new SubmissionEditWindowGuard());
            $this->registerGuard(new SubmissionEditAccessGuard());
            return;
        }

        foreach ($guards as $guard) {
            $this->registerGuard($guard);
        }
    }

    /**
     * @param GuardInterface|string $guard
     */
    public function registerGuard($guard): void
    {
        if (is_string($guard)) {
            if (!class_exists($guard)) {
                return;
            }
            $guard = new $guard();
        }

        if (!$guard instanceof GuardInterface) {
            return;
        }

        $this->guards[] = $guard;
    }

    /**
     * Evaluate registered guards in priority order.
     *
     * @return array{blocked:bool,message?:string,key?:string}
     */
    public function evaluate(int $form_id, array $context = []): array
    {
        if (empty($this->guards)) {
            return ['blocked' => false];
        }

        usort($this->guards, function (GuardInterface $a, GuardInterface $b) {
            return $a->getPriority() <=> $b->getPriority();
        });

        foreach ($this->guards as $guard) {
            $result = $guard->check($form_id, $context);
            if (!empty($result['blocked'])) {
                $result['key'] = $guard->getKey();
                return $result;
            }
        }

        return ['blocked' => false];
    }
}
