<?php

declare(strict_types=1);

namespace App\Framework\Console;

use App\Framework\Console\Screen\Cursor;
use App\Framework\Console\Screen\Display;
use App\Framework\Console\Screen\ScreenManager;

final readonly class ConsoleOutput implements ConsoleOutputInterface
{
    public Cursor $cursor;

    public Display $display;

    public ScreenManager $screen;

    public function __construct()
    {
        $this->cursor = new Cursor($this);
        $this->display = new Display($this);
        $this->screen = new ScreenManager($this);
    }

    /**
     * Schreibt Text mit optionalem Stil.
     */
    public function write(string $message, ConsoleStyle|ConsoleColor|null $style = null): void
    {
        if ($style instanceof ConsoleColor) {
            // Abwärtskompatibilität
            echo $style->toAnsi() . $message . ConsoleColor::RESET->toAnsi();
        } elseif ($style instanceof ConsoleStyle) {
            echo $style->apply($message);
        } else {
            echo $message;
        }
    }

    /**
     * Schreibt rohe ANSI-Sequenzen ohne Verarbeitung.
     */
    public function writeRaw(string $raw): void
    {
        echo $raw;
    }

    /**
     * Setzt den Fenstertitel.
     */
    public function writeWindowTitle(string $title, int $mode = 0): void
    {
        $this->writeRaw("\033]$mode;{$title}\007");
    }

    /**
     * Schreibt eine Zeile mit optionalem Stil.
     */
    public function writeLine(string $message = '', ConsoleStyle|ConsoleColor|null $color = null): void
    {
        $this->write($message . PHP_EOL, $color);
    }

    /**
     * Schreibt eine Erfolgsmeldung.
     */
    public function writeSuccess(string $message): void
    {
        $this->writeLine('✓ ' . $message, ConsoleStyle::success());
    }

    /**
     * Schreibt eine Fehlermeldung.
     */
    public function writeError(string $message): void
    {
        $this->writeLine('✗ ' . $message, ConsoleStyle::error());
    }

    /**
     * Schreibt eine Warnmeldung.
     */
    public function writeWarning(string $message): void
    {
        $this->writeLine('⚠ ' . $message, ConsoleStyle::warning());
    }

    /**
     * Schreibt eine Infomeldung.
     */
    public function writeInfo(string $message): void
    {
        $this->writeLine('ℹ ' . $message, ConsoleStyle::info());
    }

    /**
     * Fügt eine oder mehrere Leerzeilen ein.
     */
    public function newLine(int $count = 1): void
    {
        echo str_repeat(PHP_EOL, $count);
    }

    /**
     * Stellt eine Frage und gibt die Antwort zurück.
     */
    public function askQuestion(string $question, ?string $default = null): string
    {
        $prompt = $question;
        if ($default !== null) {
            $prompt .= " [{$default}]";
        }
        $prompt .= ': ';

        $this->write($prompt, ConsoleColor::BRIGHT_CYAN);

        $answer = trim(fgets(STDIN));

        return $answer === '' && $default !== null ? $default : $answer;
    }

    /**
     * Stellt eine Ja/Nein-Frage.
     */
    public function confirm(string $question, bool $default = false): bool
    {
        $defaultText = $default ? 'Y/n' : 'y/N';
        $answer = $this->askQuestion("{$question} [{$defaultText}]");

        if ($answer === '') {
            return $default;
        }

        return in_array(strtolower($answer), ['y', 'yes', 'ja', '1', 'true']);
    }

    /**
     * Prüft, ob der Output zu einem Terminal geht.
     */
    public function isTerminal(): bool
    {
        return function_exists('posix_isatty') && posix_isatty(STDOUT);
    }
}
