<?php

declare(strict_types=1);

namespace App\Framework\Console\Screen;

use App\Framework\Console\ConsoleOutput;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\DateTime\Timer;

/**
 * Verwaltet intelligentes Bildschirm-Management.
 */
final class ScreenManager
{
    private ClearStrategy $strategy = ClearStrategy::SMART;

    private bool $interactiveMode = false;

    private ?ScreenType $lastScreenType = null;

    private int $screenCount = 0;

    public function __construct(
        private readonly ConsoleOutput $output
    ) {
    }

    /**
     * Setzt die Löschstrategie.
     */
    public function setStrategy(ClearStrategy $strategy): self
    {
        $this->strategy = $strategy;

        return $this;
    }

    /**
     * Aktiviert/deaktiviert den interaktiven Modus.
     */
    public function setInteractiveMode(bool $interactive = true): self
    {
        $this->interactiveMode = $interactive;

        return $this;
    }

    /**
     * Markiert den Beginn eines neuen Bildschirms.
     * Diese Methode rufst du VOR der Ausgabe auf.
     */
    public function new(ScreenType $type = ScreenType::CONTENT): self
    {
        if ($this->shouldClear($type)) {
            $this->output->display->clear();
        }

        $this->lastScreenType = $type;
        $this->screenCount++;

        return $this;
    }

    /**
     * Convenience-Methoden für häufige Screen-Typen.
     */
    public function newMenu(): self
    {
        return $this->new(ScreenType::MENU);
    }

    public function newDialog(): self
    {
        return $this->new(ScreenType::DIALOG);
    }

    public function newContent(): self
    {
        return $this->new(ScreenType::CONTENT);
    }

    public function newLog(): self
    {
        return $this->new(ScreenType::LOG);
    }

    public function newProgress(): self
    {
        return $this->new(ScreenType::PROGRESS);
    }

    /**
     * Zeigt eine temporäre Nachricht für eine bestimmte Zeit an.
     */
    public function temporary(string $message, Timer $timer, int $seconds = 2): self
    {
        $this->output->writeLine($message);
        $timer->sleep(Duration::fromSeconds($seconds));
        $this->output->display->clearLine();

        return $this;
    }

    /**
     * Wartet auf Benutzereingabe.
     */
    public function waitForInput(): self
    {
        if ($this->output->isTerminal()) {
            fread(STDIN, 1);
        }

        return $this;
    }

    /**
     * Entscheidet, ob der Bildschirm gelöscht werden soll.
     */
    private function shouldClear(ScreenType $type): bool
    {
        if (! $this->output->isTerminal()) {
            return false;
        }

        return match($this->strategy) {
            ClearStrategy::NEVER => false,
            ClearStrategy::ALWAYS => true,
            ClearStrategy::ON_NEW_SCREEN => $type === ScreenType::MENU || $type === ScreenType::DIALOG,
            ClearStrategy::SMART => $this->shouldClearSmart($type),
        };
    }

    /**
     * Intelligente Entscheidung für das Löschen.
     */
    private function shouldClearSmart(ScreenType $type): bool
    {
        // Nie löschen für Logs und Progress
        if ($type === ScreenType::LOG || $type === ScreenType::PROGRESS) {
            return false;
        }

        // Immer löschen für Menüs und Dialoge im interaktiven Modus
        if ($this->interactiveMode && ($type === ScreenType::MENU || $type === ScreenType::DIALOG)) {
            return true;
        }

        // Für Content: nur löschen wenn der letzte Screen ein anderer Typ war
        if ($type === ScreenType::CONTENT) {
            return $this->lastScreenType !== null && $this->lastScreenType !== ScreenType::CONTENT;
        }

        return false;
    }
}
