<?php

namespace App\Filament\Widgets\Server;

use App\Filament\Concerns\CachesWidgetData;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;

class SystemHealthWidget extends StatsOverviewWidget
{
    use CachesWidgetData;

    protected ?string $heading = 'System Health';

    protected static ?int $sort = 1;

    protected ?string $pollingInterval = null;

    protected function getCacheTtl(): int
    {
        return 86400; // 1 day
    }

    protected function getStats(): array
    {
        return [
            $this->getPhpVersionStat(),
            $this->getMailStat(),
            $this->getDatabaseStat(),
            $this->getStorageStat(),
        ];
    }

    protected function getPhpVersionStat(): Stat
    {
        $phpVersion = PHP_VERSION;
        $majorVersion = (int) explode('.', $phpVersion)[0];

        return Stat::make('PHP Version', $this->obscureVersion($phpVersion))
            ->description($majorVersion >= 8 ? 'Up to date' : 'Consider upgrading')
            ->descriptionIcon($majorVersion >= 8 ? 'heroicon-m-check-circle' : 'heroicon-m-exclamation-triangle')
            ->color($majorVersion >= 8 ? 'success' : 'warning');
    }

    protected function obscureVersion(string $version): string
    {
        $parts = explode('.', $version);
        if (count($parts) >= 2) {
            return $parts[0].'.'.$parts[1].'.x';
        }

        return $version;
    }

    protected function getMailStat(): Stat
    {
        $mailer = config('mail.default');
        $mailerConfig = config("mail.mailers.{$mailer}");
        $transport = $mailerConfig['transport'] ?? $mailer;

        $isProduction = in_array($transport, ['smtp', 'ses', 'postmark', 'mailgun', 'resend']);
        $isDisabled = in_array($transport, ['null', 'array']);

        $host = $mailerConfig['host'] ?? null;
        $isLocalhost = in_array($host, ['localhost', '127.0.0.1', '::1']);

        if ($isProduction && $isLocalhost) {
            $description = $host;
            $color = 'warning';
            $icon = 'heroicon-m-exclamation-triangle';
        } elseif ($isProduction) {
            $description = $transport === 'smtp' ? $host : 'Connected';
            $color = 'success';
            $icon = 'heroicon-m-check-circle';
        } elseif ($isDisabled) {
            $description = 'Mail disabled';
            $color = 'danger';
            $icon = 'heroicon-m-x-circle';
        } else {
            $description = 'Not sending real emails';
            $color = 'warning';
            $icon = 'heroicon-m-exclamation-triangle';
        }

        return Stat::make('Mail', ucfirst($transport))
            ->description($description)
            ->descriptionIcon($icon)
            ->color($color);
    }

    protected function getDatabaseStat(): Stat
    {
        $connection = config('database.default');
        $driver = config("database.connections.{$connection}.driver");

        try {
            DB::connection()->getPdo();
            $status = 'Connected';
            $color = 'success';
            $icon = 'heroicon-m-check-circle';
        } catch (\Exception) {
            $status = 'Error';
            $color = 'danger';
            $icon = 'heroicon-m-x-circle';
        }

        return Stat::make('Database', ucfirst($driver))
            ->description($status)
            ->descriptionIcon($icon)
            ->color($color);
    }

    protected function getStorageStat(): Stat
    {
        $storagePath = storage_path('app/public');

        $usedBytes = $this->cached('storage_size', function () use ($storagePath) {
            if (File::isDirectory($storagePath)) {
                return $this->getDirectorySize($storagePath);
            }

            return 0;
        });

        $usedFormatted = $this->formatBytes($usedBytes);
        $maxUploadFormatted = $this->formatBytes($this->getMaxUploadSize());

        $color = 'success';
        $description = "Max upload: {$maxUploadFormatted}";
        if ($usedBytes > 5 * 1024 * 1024 * 1024) {
            $color = 'warning';
            $description = "Consider cleanup · Max upload: {$maxUploadFormatted}";
        }
        if ($usedBytes > 10 * 1024 * 1024 * 1024) {
            $color = 'danger';
            $description = "Needs attention · Max upload: {$maxUploadFormatted}";
        }

        return Stat::make('Storage Used', $usedFormatted)
            ->description($description)
            ->descriptionIcon('heroicon-m-server-stack')
            ->color($color);
    }

    protected function getMaxUploadSize(): int
    {
        $uploadMaxFilesize = $this->convertToBytes(ini_get('upload_max_filesize') ?: '2M');
        $postMaxSize = $this->convertToBytes(ini_get('post_max_size') ?: '8M');

        return min($uploadMaxFilesize, $postMaxSize);
    }

    protected function convertToBytes(string $value): int
    {
        $value = trim($value);
        $last = strtolower($value[strlen($value) - 1]);
        $numericValue = (int) $value;

        return match ($last) {
            'g' => $numericValue * 1024 * 1024 * 1024,
            'm' => $numericValue * 1024 * 1024,
            'k' => $numericValue * 1024,
            default => $numericValue,
        };
    }

    protected function getDirectorySize(string $path): int
    {
        $size = 0;

        foreach (File::allFiles($path) as $file) {
            try {
                $size += $file->getSize();
            } catch (\Exception) {
                // Skip files that don't exist or can't be accessed
                continue;
            }
        }

        return $size;
    }

    protected function formatBytes(int $bytes): string
    {
        $units = ['B', 'KB', 'MB', 'GB'];
        $i = 0;

        while ($bytes >= 1000 && $i < count($units) - 1) {
            $bytes /= 1000;
            $i++;
        }

        return round($bytes, 2).' '.$units[$i];
    }
}
