<?php

declare(strict_types=1);

namespace App\Framework\ErrorReporting;

use DateTimeImmutable;

/**
 * Error statistics and analytics data
 */
final readonly class ErrorStatistics
{
    public function __construct(
        public int $totalErrors,
        public int $uniqueErrors,
        public array $errorsByLevel,
        public array $errorsByException,
        public array $errorsByRoute,
        public array $errorsByUser,
        public array $errorsByHour,
        public array $errorsByDay,
        public array $topErrors,
        public array $trendingErrors,
        public float $errorRate,
        public array $responseTimeImpact,
        public array $environmentBreakdown,
        public DateTimeImmutable $periodStart,
        public DateTimeImmutable $periodEnd
    ) {
    }

    /**
     * Create empty statistics
     */
    public static function empty(): self
    {
        return new self(
            totalErrors: 0,
            uniqueErrors: 0,
            errorsByLevel: [],
            errorsByException: [],
            errorsByRoute: [],
            errorsByUser: [],
            errorsByHour: [],
            errorsByDay: [],
            topErrors: [],
            trendingErrors: [],
            errorRate: 0.0,
            responseTimeImpact: [],
            environmentBreakdown: [],
            periodStart: new DateTimeImmutable(),
            periodEnd: new DateTimeImmutable()
        );
    }

    /**
     * Get total critical errors (emergency, alert, critical levels)
     */
    public function getCriticalErrorCount(): int
    {
        return ($this->errorsByLevel['emergency'] ?? 0) +
               ($this->errorsByLevel['alert'] ?? 0) +
               ($this->errorsByLevel['critical'] ?? 0);
    }

    /**
     * Get error rate as percentage
     */
    public function getErrorRatePercentage(): float
    {
        return round($this->errorRate * 100, 2);
    }

    /**
     * Get most problematic route
     */
    public function getMostProblematicRoute(): ?array
    {
        if (empty($this->errorsByRoute)) {
            return null;
        }

        $route = array_key_first($this->errorsByRoute);
        $count = reset($this->errorsByRoute);

        return [
            'route' => $route,
            'count' => $count,
            'percentage' => $this->totalErrors > 0 ? round(($count / $this->totalErrors) * 100, 2) : 0,
        ];
    }

    /**
     * Get most frequent exception
     */
    public function getMostFrequentException(): ?array
    {
        if (empty($this->errorsByException)) {
            return null;
        }

        $exception = array_key_first($this->errorsByException);
        $count = reset($this->errorsByException);

        return [
            'exception' => $exception,
            'count' => $count,
            'percentage' => $this->totalErrors > 0 ? round(($count / $this->totalErrors) * 100, 2) : 0,
        ];
    }

    /**
     * Get peak error hour
     */
    public function getPeakErrorHour(): ?array
    {
        if (empty($this->errorsByHour)) {
            return null;
        }

        $hour = array_key_first($this->errorsByHour);
        $count = reset($this->errorsByHour);

        return [
            'hour' => $hour,
            'count' => $count,
            'time' => sprintf('%02d:00', $hour),
        ];
    }

    /**
     * Get error trend direction
     */
    public function getErrorTrend(): string
    {
        if (count($this->errorsByDay) < 2) {
            return 'stable';
        }

        $days = array_values($this->errorsByDay);
        $recent = array_slice($days, -3); // Last 3 days
        $previous = array_slice($days, -6, 3); // Previous 3 days

        if (empty($recent) || empty($previous)) {
            return 'stable';
        }

        $recentAvg = array_sum($recent) / count($recent);
        $previousAvg = array_sum($previous) / count($previous);

        $change = $previousAvg > 0 ? (($recentAvg - $previousAvg) / $previousAvg) * 100 : 0;

        if ($change > 20) {
            return 'increasing';
        } elseif ($change < -20) {
            return 'decreasing';
        } else {
            return 'stable';
        }
    }

    /**
     * Get error distribution health score (0-100)
     */
    public function getHealthScore(): int
    {
        $score = 100;

        // Penalize high error rates
        if ($this->errorRate > 0.05) { // > 5%
            $score -= 30;
        } elseif ($this->errorRate > 0.02) { // > 2%
            $score -= 15;
        } elseif ($this->errorRate > 0.01) { // > 1%
            $score -= 5;
        }

        // Penalize critical errors
        $criticalCount = $this->getCriticalErrorCount();
        if ($criticalCount > 0) {
            $score -= min(40, $criticalCount * 5);
        }

        // Penalize trending up
        if ($this->getErrorTrend() === 'increasing') {
            $score -= 15;
        }

        // Penalize concentrated errors (single route causing many errors)
        $topRoute = $this->getMostProblematicRoute();
        if ($topRoute && $topRoute['percentage'] > 50) {
            $score -= 10;
        }

        return max(0, $score);
    }

    /**
     * Get insights and recommendations
     */
    public function getInsights(): array
    {
        $insights = [];

        // Critical error insight
        $criticalCount = $this->getCriticalErrorCount();
        if ($criticalCount > 0) {
            $insights[] = [
                'type' => 'critical',
                'message' => "Found {$criticalCount} critical errors that require immediate attention.",
                'priority' => 'high',
            ];
        }

        // Error rate insight
        if ($this->errorRate > 0.05) {
            $insights[] = [
                'type' => 'error_rate',
                'message' => sprintf('Error rate is %.2f%%, which is above the recommended threshold of 2%%.', $this->getErrorRatePercentage()),
                'priority' => 'high',
            ];
        }

        // Route concentration insight
        $topRoute = $this->getMostProblematicRoute();
        if ($topRoute && $topRoute['percentage'] > 40) {
            $insights[] = [
                'type' => 'route_concentration',
                'message' => sprintf('Route "%s" accounts for %.1f%% of all errors. Consider reviewing this endpoint.', $topRoute['route'], $topRoute['percentage']),
                'priority' => 'medium',
            ];
        }

        // Exception concentration insight
        $topException = $this->getMostFrequentException();
        if ($topException && $topException['percentage'] > 50) {
            $insights[] = [
                'type' => 'exception_concentration',
                'message' => sprintf('Exception "%s" accounts for %.1f%% of all errors. This indicates a systemic issue.', basename($topException['exception']), $topException['percentage']),
                'priority' => 'medium',
            ];
        }

        // Trend insight
        $trend = $this->getErrorTrend();
        if ($trend === 'increasing') {
            $insights[] = [
                'type' => 'trend',
                'message' => 'Error trend is increasing over the last few days. Monitor closely.',
                'priority' => 'medium',
            ];
        } elseif ($trend === 'decreasing') {
            $insights[] = [
                'type' => 'trend',
                'message' => 'Error trend is decreasing. Good progress!',
                'priority' => 'low',
            ];
        }

        // No errors insight
        if ($this->totalErrors === 0) {
            $insights[] = [
                'type' => 'no_errors',
                'message' => 'No errors recorded in this period. System is operating smoothly.',
                'priority' => 'low',
            ];
        }

        return $insights;
    }

    /**
     * Convert to array
     */
    public function toArray(): array
    {
        return [
            'total_errors' => $this->totalErrors,
            'unique_errors' => $this->uniqueErrors,
            'errors_by_level' => $this->errorsByLevel,
            'errors_by_exception' => $this->errorsByException,
            'errors_by_route' => $this->errorsByRoute,
            'errors_by_user' => $this->errorsByUser,
            'errors_by_hour' => $this->errorsByHour,
            'errors_by_day' => $this->errorsByDay,
            'top_errors' => $this->topErrors,
            'trending_errors' => $this->trendingErrors,
            'error_rate' => $this->errorRate,
            'error_rate_percentage' => $this->getErrorRatePercentage(),
            'response_time_impact' => $this->responseTimeImpact,
            'environment_breakdown' => $this->environmentBreakdown,
            'period_start' => $this->periodStart->format('c'),
            'period_end' => $this->periodEnd->format('c'),
            'critical_error_count' => $this->getCriticalErrorCount(),
            'most_problematic_route' => $this->getMostProblematicRoute(),
            'most_frequent_exception' => $this->getMostFrequentException(),
            'peak_error_hour' => $this->getPeakErrorHour(),
            'error_trend' => $this->getErrorTrend(),
            'health_score' => $this->getHealthScore(),
            'insights' => $this->getInsights(),
        ];
    }
}
