<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Schema;

class HealthController extends Controller
{
    /**
     * Lightweight liveness check.
     */
    public function basic(): JsonResponse
    {
        return response()->json(['data' => ['status' => 'ok']]);
    }

    /**
     * Full health check — super_admin only.
     */
    public function full(): JsonResponse
    {
        $user = auth()->user();
        if (! $user || ! method_exists($user, 'hasRole') || ! $user->hasRole('super_admin')) {
            return response()->json(['error' => 'forbidden'], 403);
        }

        $checks = [];
        $overall = 'ok';

        // DB
        $checks['db'] = $this->guard(function () {
            DB::connection()->select('select 1');

            return 'ok';
        });

        // Redis
        $checks['redis'] = $this->guard(function () {
            $reply = (string) Redis::connection()->command('ping');

            return $reply === 'PONG' || $reply === '+PONG' || strtoupper($reply) === 'PONG' ? 'ok' : 'fail';
        });

        // Telescope table
        $checks['telescope'] = $this->guard(fn () => Schema::hasTable('telescope_entries') ? 'ok' : 'missing');

        // Migrations pending
        $checks['migrations'] = $this->guard(function () {
            $migrator = app('migrator');
            $files = $migrator->getMigrationFiles(database_path('migrations'));
            $ran = $migrator->getRepository()->getRan();
            $pending = array_diff(array_keys($files), $ran);

            return empty($pending) ? 'ok' : ('pending=' . count($pending));
        });

        // Queue worker / Horizon
        $checks['horizon'] = $this->guard(function () {
            if (! interface_exists(\Laravel\Horizon\Contracts\MasterSupervisorRepository::class)) {
                return 'not_installed';
            }
            $repo = app(\Laravel\Horizon\Contracts\MasterSupervisorRepository::class);
            $masters = $repo->all();

            return empty($masters) ? 'no_supervisor' : 'ok';
        });

        // Disk space
        $checks['disk'] = $this->guard(function () {
            $free = @disk_free_space('/');
            $total = @disk_total_space('/');
            if (! $free || ! $total) {
                return 'unknown';
            }
            $pctFree = ($free / $total) * 100;

            return [
                'free_pct' => round($pctFree, 1),
                'free_gb' => round($free / 1024 ** 3, 1),
                'status' => $pctFree < 10 ? 'low' : 'ok',
            ];
        });

        // Backup recency
        $checks['backup'] = $this->guard(function () {
            $files = glob('/www/backup/easybox-db/*.sql.gz') ?: [];
            if (empty($files)) {
                return 'no_backups';
            }
            $newest = max(array_map('filemtime', $files));
            $ageHrs = (time() - $newest) / 3600;

            return [
                'age_hours' => round($ageHrs, 1),
                'status' => $ageHrs > 48 ? 'stale' : 'ok',
            ];
        });

        foreach ($checks as $r) {
            $status = is_array($r) ? ($r['status'] ?? 'ok') : $r;
            if (! in_array($status, ['ok'], true)) {
                $overall = 'degraded';
            }
        }

        return response()->json([
            'data' => [
                'status' => $overall,
                'checks' => $checks,
                'env' => app()->environment(),
                'at' => now()->toIso8601String(),
            ],
        ]);
    }

    /**
     * @param  callable():mixed  $cb
     */
    private function guard(callable $cb): mixed
    {
        try {
            return $cb();
        } catch (\Throwable $e) {
            return ['status' => 'error', 'message' => $e->getMessage()];
        }
    }
}
