<?php

declare(strict_types=1);

namespace App\Framework\Deployment\Pipeline\ValueObjects;

/**
 * Stage Configuration
 *
 * Configuration for a specific pipeline stage including execution parameters,
 * timeouts, and retry policies.
 */
final readonly class StageConfig
{
    /**
     * @param PipelineStage $stage Stage type
     * @param bool $enabled Whether stage is enabled
     * @param int $timeoutSeconds Maximum execution time in seconds (0 = no limit)
     * @param int $retries Number of retry attempts on failure
     * @param bool $continueOnFailure Continue pipeline even if stage fails
     * @param array<string, mixed> $parameters Stage-specific parameters
     * @param array<DeploymentEnvironment> $skipEnvironments Environments where this stage should be skipped
     */
    public function __construct(
        public PipelineStage $stage,
        public bool $enabled = true,
        public int $timeoutSeconds = 0,
        public int $retries = 0,
        public bool $continueOnFailure = false,
        public array $parameters = [],
        public array $skipEnvironments = []
    ) {}

    /**
     * Check if stage should be skipped for environment
     */
    public function shouldSkipForEnvironment(DeploymentEnvironment $environment): bool
    {
        foreach ($this->skipEnvironments as $skipEnv) {
            if ($skipEnv === $environment) {
                return true;
            }
        }

        return false;
    }

    /**
     * Get stage parameter value
     */
    public function getParameter(string $key, mixed $default = null): mixed
    {
        return $this->parameters[$key] ?? $default;
    }

    /**
     * Check if stage has timeout configured
     */
    public function hasTimeout(): bool
    {
        return $this->timeoutSeconds > 0;
    }

    /**
     * Check if stage has retries configured
     */
    public function hasRetries(): bool
    {
        return $this->retries > 0;
    }

    /**
     * Create default configuration for stage
     */
    public static function forStage(PipelineStage $stage): self
    {
        return match ($stage) {
            PipelineStage::BUILD => new self(
                stage: $stage,
                timeoutSeconds: 600, // 10 minutes
                retries: 1
            ),
            PipelineStage::TEST => new self(
                stage: $stage,
                timeoutSeconds: 300, // 5 minutes
                retries: 0,
                skipEnvironments: [DeploymentEnvironment::PRODUCTION]
            ),
            PipelineStage::SECURITY_CHECK => new self(
                stage: $stage,
                timeoutSeconds: 120, // 2 minutes
                retries: 0,
                skipEnvironments: [DeploymentEnvironment::DEVELOPMENT]
            ),
            PipelineStage::BACKUP => new self(
                stage: $stage,
                timeoutSeconds: 300, // 5 minutes
                retries: 1,
                skipEnvironments: [DeploymentEnvironment::DEVELOPMENT]
            ),
            PipelineStage::DEPLOY => new self(
                stage: $stage,
                timeoutSeconds: 600, // 10 minutes
                retries: 0
            ),
            PipelineStage::HEALTH_CHECK => new self(
                stage: $stage,
                timeoutSeconds: 60, // 1 minute
                retries: 2
            ),
            PipelineStage::CLEANUP => new self(
                stage: $stage,
                timeoutSeconds: 180, // 3 minutes
                retries: 0,
                continueOnFailure: true
            ),
            PipelineStage::ROLLBACK => new self(
                stage: $stage,
                timeoutSeconds: 300, // 5 minutes
                retries: 0
            ),
        };
    }
}
