<?php

declare(strict_types=1);

namespace App\Framework\Core;

/**
 * Einfacher Progressmeter für Konsolenanwendungen
 */
final class ProgressMeter
{
    private int $total;

    private int $current = 0;

    private int $lastPercent = 0;

    private bool $isConsole;

    private int $width;

    private string $format;

    /**
     * @param int $total Gesamtanzahl der zu verarbeitenden Elemente
     * @param int $width Breite der Fortschrittsanzeige
     * @param string $format Format der Anzeige: 'bar' für Balken, 'percent' für Prozent, 'both' für beides
     */
    public function __construct(
        int $total,
        int $width = 50,
        string $format = 'both'
    ) {
        $this->total = max(1, $total); // Verhindere Division durch Null
        $this->width = $width;
        $this->format = $format;
        $this->isConsole = php_sapi_name() === 'cli';
    }

    /**
     * Erhöht den Fortschritt um einen oder mehrere Schritte
     */
    public function advance(int $step = 1): void
    {
        $this->current += $step;

        if ($this->isConsole) {
            $percent = (int)(($this->current / $this->total) * 100);

            if ($percent > $this->lastPercent || $this->current >= $this->total) {
                $this->display();
                $this->lastPercent = $percent;
            }

            if ($this->current >= $this->total) {
                echo PHP_EOL;
            }
        }
    }

    /**
     * Zeigt den aktuellen Fortschritt an
     */
    private function display(): void
    {
        $percent = (int)(($this->current / $this->total) * 100);

        switch ($this->format) {
            case 'bar':
                $this->displayBar($percent);

                break;
            case 'percent':
                $this->displayPercent($percent);

                break;
            case 'both':
            default:
                $this->displayBoth($percent);

                break;
        }
    }

    /**
     * Zeigt einen Fortschrittsbalken an
     */
    private function displayBar(int $percent): void
    {
        $completed = (int)(($this->width * $percent) / 100);
        $remaining = $this->width - $completed;

        echo "\r[";
        echo str_repeat("=", $completed);
        echo str_repeat(" ", $remaining);
        echo "] {$this->current}/{$this->total}";
    }

    /**
     * Zeigt den Fortschritt als Prozentwert an
     */
    private function displayPercent(int $percent): void
    {
        echo "\rFortschritt: {$percent}% [{$this->current}/{$this->total}]";
    }

    /**
     * Zeigt sowohl Balken als auch Prozentwert an
     */
    private function displayBoth(int $percent): void
    {
        $completed = (int)(($this->width * $percent) / 100);
        $remaining = $this->width - $completed;

        echo "\r[";
        echo str_repeat("=", $completed);
        echo str_repeat(" ", $remaining);
        echo "] {$percent}% [{$this->current}/{$this->total}]";
    }

    /**
     * Markiert den Fortschritt als abgeschlossen
     */
    public function finish(): void
    {
        if ($this->isConsole) {
            $this->current = $this->total;
            $this->display();
            echo PHP_EOL;
        }
    }

    /**
     * Setzt den Fortschritt auf einen bestimmten Wert
     */
    public function setProgress(int $current): void
    {
        $this->current = max(0, min($current, $this->total));

        if ($this->isConsole) {
            $this->display();
        }
    }
}
