<?php

declare(strict_types=1);

namespace App\Framework\Console\Progress;

use App\Framework\Console\ConsoleColor;
use App\Framework\Console\ConsoleOutputInterface;
use App\Framework\Console\ConsoleStyle;

/**
 * Console output wrapper that provides built-in progress tracking
 */
final class ProgressAwareOutput implements ConsoleOutputInterface
{
    private readonly ProgressFactory $progressFactory;

    private ?ProgressInterface $currentProgress = null;

    public function __construct(
        private readonly ConsoleOutputInterface $output
    ) {
        $this->progressFactory = new ProgressFactory($this->output);
    }

    public function writeLine(string $message = '', ?ConsoleColor $color = null): void
    {
        $this->output->writeLine($message, $color);
    }

    public function write(string $message, null|ConsoleColor|ConsoleStyle $style = null): void
    {
        $this->output->write($message, $style);
    }

    public function writeSuccess(string $message): void
    {
        $this->output->writeSuccess($message);
    }

    public function writeError(string $message): void
    {
        $this->output->writeError($message);
    }

    public function writeWarning(string $message): void
    {
        $this->output->writeWarning($message);
    }

    public function writeInfo(string $message): void
    {
        $this->output->writeInfo($message);
    }

    public function newLine(int $count = 1): void
    {
        $this->output->newLine($count);
    }

    public function askQuestion(string $question, ?string $default = null): string
    {
        return $this->output->askQuestion($question, $default);
    }

    public function writeWindowTitle(string $title, int $mode = 0): void
    {
        $this->output->writeWindowTitle($title, $mode);
    }

    public function confirm(string $question, bool $default = false): bool
    {
        return $this->output->confirm($question, $default);
    }

    /**
     * Create a progress tracker for long-running operations
     */
    public function createProgress(int $total, string $title = 'Progress'): ProgressTracker
    {
        return $this->progressFactory->createTracker($total, $title);
    }

    /**
     * Create a spinner for indeterminate operations
     */
    public function createSpinner(string $title = 'Working'): SpinnerProgress
    {
        return $this->progressFactory->createSpinner($title);
    }

    /**
     * Create a simple progress bar
     */
    public function createProgressBar(int $width = 50): ProgressBar
    {
        return $this->progressFactory->createBar($width);
    }

    /**
     * Execute a callback with progress tracking
     */
    public function withProgress(int $total, string $title, callable $callback): mixed
    {
        $progress = $this->createProgress($total, $title);

        try {
            return $callback($progress);
        } finally {
            if (! $progress->isFinished()) {
                $progress->finish();
            }
        }
    }

    /**
     * Execute a callback with spinner progress
     */
    public function withSpinner(string $title, callable $callback): mixed
    {
        $spinner = $this->createSpinner($title);

        try {
            return $callback($spinner);
        } finally {
            if (! $spinner->isFinished()) {
                $spinner->finish();
            }
        }
    }

    /**
     * Set the current progress indicator for command use
     */
    public function setCurrentProgress(?ProgressInterface $progress): void
    {
        $this->currentProgress = $progress;
    }

    /**
     * Get the current progress indicator
     */
    public function getCurrentProgress(): ?ProgressInterface
    {
        return $this->currentProgress;
    }

    /**
     * Get the underlying output interface
     */
    public function getOutput(): ConsoleOutputInterface
    {
        return $this->output;
    }
}
