<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

/**
 * Lightweight self-health probe. Runs on the box, so it can't catch total
 * outages — pair with external uptime monitoring (UptimeRobot, Better Stack)
 * pointing at /up.
 *
 * Tests:
 *   - DB connectivity (central connection: SELECT 1)
 *   - Cache write/read (Redis if configured)
 *   - Public storage disk write/read
 *   - Most recent tenant backup age (warn if > 30h)
 *
 * On any failure, pushes a short Telegram alert to HEALTH_ALERT_CHAT_ID via
 * HEALTH_ALERT_BOT_TOKEN (env). Dedups identical failures within 30 minutes
 * via cache to avoid spamming on each cron tick.
 */
class HealthCheckCommand extends Command
{
    protected $signature = 'health:check
                            {--silent : Do not echo OK output (for cron)}';

    protected $description = 'Probe DB / cache / storage / backup freshness; alert via Telegram on failure.';

    public function handle(): int
    {
        $issues = [];

        try {
            DB::connection()->select('SELECT 1');
        } catch (\Throwable $e) {
            $issues[] = 'DB: ' . substr($e->getMessage(), 0, 120);
        }

        try {
            $stamp = 'hc:' . (string) microtime(true);
            Cache::put('health:probe', $stamp, 30);
            if (Cache::get('health:probe') !== $stamp) {
                $issues[] = 'Cache: write/read mismatch';
            }
        } catch (\Throwable $e) {
            $issues[] = 'Cache: ' . substr($e->getMessage(), 0, 120);
        }

        try {
            $f = 'health/' . md5((string) microtime(true)) . '.txt';
            Storage::disk('public')->put($f, 'ok');
            if (Storage::disk('public')->get($f) !== 'ok') {
                $issues[] = 'Storage: write/read mismatch';
            }
            Storage::disk('public')->delete($f);
        } catch (\Throwable $e) {
            $issues[] = 'Storage: ' . substr($e->getMessage(), 0, 120);
        }

        try {
            $newest = collect(Storage::disk('local')->allFiles('backups'))
                ->map(fn ($f) => Storage::disk('local')->lastModified($f))
                ->max();
            if ($newest && (time() - $newest) > 30 * 3600) {
                $age = round((time() - $newest) / 3600, 1);
                $issues[] = "Backup: cel mai recent are {$age}h (expectat <30h).";
            }
        } catch (\Throwable $e) {
            // Backup folder might be empty on a fresh install — not an alert.
        }

        if (empty($issues)) {
            if (! $this->option('silent')) {
                $this->info('Health OK · ' . now()->toIso8601String());
            }
            return self::SUCCESS;
        }

        $signature = md5(implode('|', $issues));
        $dedupKey = "health:alert:{$signature}";
        if (! Cache::has($dedupKey)) {
            $this->pushTelegramAlert($issues);
            Cache::put($dedupKey, 1, 30 * 60);   // 30-min cooldown per fingerprint
        }

        foreach ($issues as $i) $this->error($i);
        return self::FAILURE;
    }

    private function pushTelegramAlert(array $issues): void
    {
        $bot = env('HEALTH_ALERT_BOT_TOKEN');
        $chat = env('HEALTH_ALERT_CHAT_ID');
        if (! $bot || ! $chat) {
            Log::warning('health:check failed but HEALTH_ALERT_BOT_TOKEN/CHAT_ID not set', [
                'issues' => $issues,
            ]);
            return;
        }

        $body = "🚨 <b>AutoCRM health alert</b>\n"
            . implode("\n", array_map(fn ($i) => '• ' . htmlspecialchars($i), $issues))
            . "\n\n" . config('app.url', 'service.mir.md');

        try {
            Http::asJson()
                ->timeout(10)
                ->post("https://api.telegram.org/bot{$bot}/sendMessage", [
                    'chat_id' => $chat,
                    'text' => $body,
                    'parse_mode' => 'HTML',
                ]);
        } catch (\Throwable $e) {
            Log::warning('health:check telegram alert failed', ['err' => $e->getMessage()]);
        }
    }
}
