<?php

declare(strict_types=1);

namespace App\Framework\Console;

/**
 * Result of command validation containing errors, warnings and metadata
 */
final readonly class ValidationResult
{
    public function __construct(
        public bool $valid,
        public array $errors,
        public array $warnings,
        public ?string $commandName = null
    ) {
    }

    /**
     * Check if validation passed (no errors)
     */
    public function isValid(): bool
    {
        return $this->valid;
    }

    /**
     * Get all validation errors
     */
    public function getErrors(): array
    {
        return $this->errors;
    }

    /**
     * Get all validation warnings
     */
    public function getWarnings(): array
    {
        return $this->warnings;
    }

    /**
     * Get errors by type
     */
    public function getErrorsByType(string $type): array
    {
        return array_filter($this->errors, fn ($error) => $error['type'] === $type);
    }

    /**
     * Get warnings by type
     */
    public function getWarningsByType(string $type): array
    {
        return array_filter($this->warnings, fn ($warning) => $warning['type'] === $type);
    }

    /**
     * Get errors by severity level
     */
    public function getErrorsBySeverity(string $severity): array
    {
        return array_filter($this->errors, fn ($error) => $error['severity'] === $severity);
    }

    /**
     * Get warnings by severity level
     */
    public function getWarningsBySeverity(string $severity): array
    {
        return array_filter($this->warnings, fn ($warning) => $warning['severity'] === $severity);
    }

    /**
     * Check if there are critical errors
     */
    public function hasCriticalErrors(): bool
    {
        return ! empty($this->getErrorsBySeverity('critical'));
    }

    /**
     * Get total issue count
     */
    public function getTotalIssueCount(): int
    {
        return count($this->errors) + count($this->warnings);
    }

    /**
     * Get command name or class name
     */
    public function getCommandName(): ?string
    {
        return $this->commandName;
    }

    /**
     * Format validation result as human-readable text
     */
    public function formatAsText(): string
    {
        $output = [];

        if ($this->commandName) {
            $output[] = "Validation Result for: {$this->commandName}";
            $output[] = str_repeat('=', 50);
        }

        if ($this->valid) {
            $output[] = "✅ Command validation passed";
        } else {
            $output[] = "❌ Command validation failed";
        }

        if (! empty($this->errors)) {
            $output[] = "";
            $output[] = "ERRORS:";
            foreach ($this->errors as $error) {
                $severity = strtoupper($error['severity']);
                $output[] = "  [{$severity}] {$error['message']}";
                if (isset($error['suggestion'])) {
                    $output[] = "    💡 {$error['suggestion']}";
                }
            }
        }

        if (! empty($this->warnings)) {
            $output[] = "";
            $output[] = "WARNINGS:";
            foreach ($this->warnings as $warning) {
                $severity = strtoupper($warning['severity']);
                $output[] = "  [{$severity}] {$warning['message']}";
                if (isset($warning['suggestion'])) {
                    $output[] = "    💡 {$warning['suggestion']}";
                }
            }
        }

        if (empty($this->errors) && empty($this->warnings)) {
            $output[] = "No issues found!";
        }

        return implode("\n", $output);
    }

    /**
     * Convert to array format
     */
    public function toArray(): array
    {
        return [
            'valid' => $this->valid,
            'command_name' => $this->commandName,
            'errors' => $this->errors,
            'warnings' => $this->warnings,
            'summary' => [
                'total_errors' => count($this->errors),
                'total_warnings' => count($this->warnings),
                'critical_errors' => count($this->getErrorsBySeverity('critical')),
                'has_critical' => $this->hasCriticalErrors(),
            ],
        ];
    }

    /**
     * Create a successful validation result
     */
    public static function success(?string $commandName = null): self
    {
        return new self(
            valid: true,
            errors: [],
            warnings: [],
            commandName: $commandName
        );
    }

    /**
     * Create a failed validation result
     */
    public static function failure(array $errors, array $warnings = [], ?string $commandName = null): self
    {
        return new self(
            valid: false,
            errors: $errors,
            warnings: $warnings,
            commandName: $commandName
        );
    }
}
