<?php

declare(strict_types=1);

namespace App\Framework\Deployment\Pipeline\Stages;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Deployment\Pipeline\ValueObjects\DeploymentEnvironment;
use App\Framework\Deployment\Pipeline\ValueObjects\PipelineStage;
use App\Framework\Deployment\Pipeline\ValueObjects\StageResult;
use App\Framework\Logging\Logger;
use App\Framework\Process\Process;
use App\Framework\Process\ValueObjects\Command;

/**
 * Build Stage
 *
 * Builds application assets and dependencies (composer, npm).
 */
final readonly class BuildStage implements PipelineStageInterface
{
    public function __construct(
        private Process $process,
        private Logger $logger
    ) {}

    public function getStage(): PipelineStage
    {
        return PipelineStage::BUILD;
    }

    public function execute(DeploymentEnvironment $environment): StageResult
    {
        $startTime = microtime(true);

        $this->logger->info('Starting build stage', [
            'environment' => $environment->value
        ]);

        try {
            // Install composer dependencies
            $composerResult = $this->process->run(
                Command::fromString('composer install --no-dev --optimize-autoloader'),
                timeout: Duration::fromMinutes(5)
            );

            if (!$composerResult->isSuccess()) {
                throw new \RuntimeException('Composer install failed: ' . $composerResult->stderr);
            }

            // Build npm assets
            $npmResult = $this->process->run(
                Command::fromString('npm run build'),
                timeout: Duration::fromMinutes(10)
            );

            if (!$npmResult->isSuccess()) {
                throw new \RuntimeException('NPM build failed: ' . $npmResult->stderr);
            }

            $duration = Duration::fromSeconds(microtime(true) - $startTime);

            return StageResult::success(
                stage: $this->getStage(),
                duration: $duration,
                output: "Composer and NPM build completed successfully"
            );

        } catch (\Throwable $e) {
            $duration = Duration::fromSeconds(microtime(true) - $startTime);

            $this->logger->error('Build stage failed', [
                'error' => $e->getMessage()
            ]);

            return StageResult::failure(
                stage: $this->getStage(),
                duration: $duration,
                error: $e->getMessage()
            );
        }
    }

    public function canRollback(): bool
    {
        return false; // Build artifacts can't be "rolled back"
    }

    public function rollback(DeploymentEnvironment $environment): StageResult
    {
        throw new \LogicException('Build stage does not support rollback');
    }

    public function getDescription(): string
    {
        return $this->getStage()->getDescription();
    }

    public function shouldSkip(DeploymentEnvironment $environment): bool
    {
        return false; // Always run build
    }
}
