<?php

declare(strict_types=1);

namespace ReallySimplePlugins\RSS\Core\Features\Pro\Vulnerability\Services;

use ReallySimplePlugins\RSS\Core\Features\Pro\Vulnerability\Services\Policies\VulnerabilityEmailNotificationPolicy;

final class VulnerabilityMeasuresMailQueue
{
    /**
     * A de-duplicated queue of component names per action.
     *
     * @var array<string, array<string, true>>
     */
    private array $queue = [];

    /**
     * Service responsible for sending vulnerability-related emails.
     */
    private VulnerabilityMeasuresEmailService $mailer;

    /**
     * Policy that determines whether email notifications should be sent.
     */
    private VulnerabilityEmailNotificationPolicy $emailNotificationPolicy;

    public function __construct(
        VulnerabilityMeasuresEmailService $mailer,
        VulnerabilityEmailNotificationPolicy $emailNotificationPolicy
    )
    {
        $this->mailer = $mailer;
        $this->emailNotificationPolicy = $emailNotificationPolicy;
    }

    /**
     * Queue a component name for a specific action.
     *
     * The queue is de-duplicated per action: the same component
     * can only be queued once for a given action.
     *
     * @param string $action        The action identifier (e.g. update_scheduled).
     * @param string $componentName The human-readable component name.
     */
    public function queue(string $action, string $componentName): void
    {
        if( $this->emailNotificationPolicy->shouldSend() && $this->emailNotificationPolicy->canSend() ) {
            if (!isset($this->queue[$action])) {
                $this->queue[$action] = [];
            }
            $this->queue[$action][$componentName] = true;
        }
    }

    /**
     * Flush the queued actions and send the corresponding emails.
     *
     * For each action, the first component name is used as the
     * primary subject, while the remaining number of components
     * is passed as a count.
     *
     * After flushing, the queue is cleared.
     */
    public function flush(): void
    {
        foreach ($this->queue as $type => $names) {
            $componentNames = array_keys($names);
            $first = array_shift($componentNames);
            if($first === null) {
                continue;
            }
            $count = count($componentNames);

            switch ($type) {
                case 'update_scheduled':
                    $this->mailer->sendUpdateScheduled($first, $count);
                    break;
                case 'update_failed':
                    $this->mailer->sendUpdateFailed($first, $count);
                    break;
                case 'update_success':
                    $this->mailer->sendUpdateSuccess($first, $count);
                    break;
                case 'quarantine_scheduled':
                    $this->mailer->sendQuarantineScheduled($first, $count);
                    break;
                case 'quarantine':
                    $this->mailer->sendQuarantineSuccess($first, $count);
                    break;
                case 'end_process':
                    $this->mailer->sendEndProcess($first, $count);
                    break;
                default:
                    // no-op
                    break;
            }
        }
        $this->queue = [];
    }

    /**
     * show mail queue
     *
     * @return \true[][]
     */
    public function getQueue()
    {
        return $this->queue;
    }
}
