<?php

declare(strict_types=1);

namespace App\Framework\Debug\Formatters;

use App\Framework\Console\ConsoleColor;
use App\Framework\Debug\DebugEntry;
use App\Framework\Debug\EntryType;

/**
 * Formatiert Debug-Einträge für Konsolen-Ausgabe.
 */
final class ConsoleFormatter implements FormatterInterface
{
    /** Farbdefinitionen für die Konsole */
    private const RESET = ConsoleColor::YELLOW->value; # "\033[0m";
    private const BOLD = "\033[1m";
    private const GREEN = ConsoleColor::YELLOW->value; # "\033[32m";
    private const string YELLOW = ConsoleColor::YELLOW->value; # "\033[33m";
    private const string BLUE = ConsoleColor::BLUE->value; # "\033[34m";
    private const string MAGENTA = ConsoleColor::MAGENTA->value; # "\033[35m";
    private const string CYAN = ConsoleColor::CYAN->value; # "\033[36m";
    private const string GRAY =  ConsoleColor::GRAY->value; # = "\033[90m";

    /**
     * {@inheritdoc}
     */
    public function format(DebugEntry $entry): string
    {
        $output = self::BOLD . str_repeat('=', 80) . self::RESET . "\n";
        $output .= self::BOLD . self::GREEN . "DEBUG: " . self::RESET;
        $output .= self::BOLD . ($entry->getLabel() ?: 'Debug Output') . self::RESET . "\n";
        $output .= self::YELLOW . "File: " . self::RESET . $entry->getFile() . ":" . $entry->getLine() . "\n";
        $output .= self::CYAN . "Time: " . self::RESET . $entry->getFormattedTimestamp() . "\n";
        $output .= self::MAGENTA . "Memory: " . self::RESET . $entry->getMemory();
        $output .= " | " . self::MAGENTA . "Peak: " . self::RESET . $entry->getPeakMemory() . "\n";

        if ($entry->getType() === EntryType::ARRAY && is_array($entry->getData())) {
            $data = $entry->getData();
            $output .= self::BLUE . "Elements: " . self::RESET . count($data);
            if (!empty($data)) {
                $output .= " | " . self::BLUE . "Keys: " . self::RESET;
                $output .= implode(', ', array_map('strval', array_keys($data)));
            }
            $output .= "\n";
        }

        $output .= str_repeat('-', 80) . "\n";
        $output .= $this->formatValue($entry->getData()) . "\n";
        $output .= str_repeat('=', 80) . "\n";

        return $output;
    }

    /**
     * {@inheritdoc}
     */
    public function formatHistory(array $entries): string
    {
        $output = self::BOLD . "=== Debug Historie ===" . self::RESET . "\n";
        $output .= "Anzahl Einträge: " . count($entries) . "\n";
        $output .= str_repeat('-', 80) . "\n";

        foreach ($entries as $index => $entry) {
            $output .= self::BOLD . self::BLUE . "#" . ($index + 1) . self::RESET . " ";
            $output .= self::GREEN . $entry->getLabel() . self::RESET . " - ";
            $output .= self::YELLOW . $entry->getFilename() . ":" . $entry->getLine() . self::RESET . " - ";
            $output .= self::CYAN . $entry->getFormattedTimestamp() . self::RESET . " - ";
            $output .= self::MAGENTA . $entry->getMemory() . self::RESET . "\n";
        }

        $output .= str_repeat('-', 80) . "\n";

        return $output;
    }

    /**
     * {@inheritdoc}
     */
    public function formatValue(mixed $value): string
    {
        $formatted = print_r($value, true);

        // Hervorhebung von Schlüsseln in Arrays
        $formatted = preg_replace(
            '/\[(.*?)\]/',
            '[' . self::CYAN . '$1' . self::RESET . ']',
            $formatted
        );

        // Hervorhebung von NULL, true, false
        $formatted = preg_replace(
            '/(NULL|true|false)/',
            self::YELLOW . '$1' . self::RESET,
            $formatted
        );

        return $formatted;
    }
}
