<?php

namespace App\Filament\Widgets;

use Filament\Widgets\Widget;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;

class QueueHealthWidget extends Widget
{
    protected string $view = 'filament.widgets.queue-health';

    protected ?string $pollingInterval = '60s';

    protected function getViewData(): array
    {
        $snapshot = Cache::get('storage:queue-health:last');
        $stalledMinutes = (int) config('storage-monitor.queue_health.stalled_minutes', 10);

        if (! is_array($snapshot)) {
            return [
                'snapshotMissing' => true,
                'connection' => (string) config('queue.default'),
                'snapshotLabel' => __('admin.ops_health.snapshot_missing'),
                'queues' => [],
                'alerts' => [],
                'alertCount' => 0,
                'stalledAssets' => 0,
                'stalledMinutes' => $stalledMinutes,
            ];
        }

        $queues = collect($snapshot['queues'] ?? [])
            ->map(fn (array $queue) => $this->formatQueue($queue))
            ->values()
            ->all();

        $alerts = collect($snapshot['alerts'] ?? [])
            ->map(fn (array $alert) => $this->formatAlert($alert))
            ->values()
            ->all();

        $snapshotAge = $this->formatSnapshotAge($snapshot['generated_at'] ?? null);
        $snapshotLabel = $snapshotAge
            ? __('admin.ops_health.snapshot_age', ['age' => $snapshotAge])
            : __('admin.ops_health.snapshot_missing');

        return [
            'snapshotMissing' => false,
            'connection' => (string) ($snapshot['connection'] ?? config('queue.default')),
            'snapshotLabel' => $snapshotLabel,
            'queues' => $queues,
            'alerts' => $alerts,
            'alertCount' => count($alerts),
            'stalledAssets' => (int) ($snapshot['stalled_assets'] ?? 0),
            'stalledMinutes' => $stalledMinutes,
            'statusSummary' => $this->summarizeSeverities($queues),
        ];
    }

    private function formatQueue(array $queue): array
    {
        $size = (int) ($queue['size'] ?? 0);
        $failed = (int) ($queue['failed'] ?? 0);
        $limits = $queue['limits'] ?? [];

        return [
            'name' => (string) ($queue['queue'] ?? 'default'),
            'size' => $size,
            'size_label' => $size < 0 ? '-' : number_format($size),
            'failed' => $failed,
            'failed_label' => number_format($failed),
            'severity' => (string) ($queue['severity'] ?? 'unknown'),
            'warning' => (int) ($limits['warning'] ?? 0),
            'critical' => (int) ($limits['critical'] ?? 0),
            'utilization_label' => $this->formatUtilizationLabel($size, $limits),
        ];
    }

    private function formatAlert(array $alert): array
    {
        return [
            'queue' => $alert['queue'] ?? null,
            'type' => (string) ($alert['type'] ?? 'unknown'),
            'severity' => (string) ($alert['severity'] ?? 'warning'),
            'size' => $alert['size'] ?? null,
            'failed' => $alert['failed'] ?? null,
            'count' => $alert['count'] ?? null,
            'older_than_minutes' => $alert['older_than_minutes'] ?? null,
        ];
    }

    private function formatSnapshotAge(?string $timestamp): ?string
    {
        if (! $timestamp) {
            return null;
        }

        try {
            return Carbon::parse($timestamp)->diffForHumans();
        } catch (\Throwable) {
            return null;
        }
    }

    private function summarizeSeverities(array $queues): array
    {
        $counts = [
            'ok' => 0,
            'warning' => 0,
            'critical' => 0,
            'unknown' => 0,
        ];

        foreach ($queues as $queue) {
            $severity = $queue['severity'] ?? 'unknown';
            if (! array_key_exists($severity, $counts)) {
                $severity = 'unknown';
            }

            $counts[$severity]++;
        }

        return collect($counts)
            ->map(fn (int $count, string $severity) => [
                'severity' => $severity,
                'label' => __('admin.ops_health.severity.'.$severity),
                'count' => $count,
            ])
            ->values()
            ->all();
    }

    private function formatUtilizationLabel(int $size, array $limits): string
    {
        if ($size < 0) {
            return __('admin.ops_health.queue.utilization_na');
        }

        $critical = (int) ($limits['critical'] ?? 0);
        $warning = (int) ($limits['warning'] ?? 0);

        if ($critical > 0) {
            $percent = (int) round(($size / $critical) * 100);

            return __('admin.ops_health.queue.utilization_of', [
                'percent' => $percent,
                'label' => __('admin.ops_health.severity.critical'),
            ]);
        }

        if ($warning > 0) {
            $percent = (int) round(($size / $warning) * 100);

            return __('admin.ops_health.queue.utilization_of', [
                'percent' => $percent,
                'label' => __('admin.ops_health.severity.warning'),
            ]);
        }

        return __('admin.ops_health.queue.utilization_na');
    }
}
