<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Enums\UserActions;
use App\Enums\UserTypes;
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
use App\Http\Controllers\Helpers\ResponseHelper;
use App\Models\User;
use App\Models\DbBackup;
use Hyperf\Stringable\Str;
use Hypervel\Http\Request;
use Hypervel\Support\Facades\Auth;
use Hypervel\Support\Facades\DB;
use Hypervel\Support\Facades\Redis;
use Hypervel\Support\Facades\Response;

class AdminConsoleController
{
    private function checkAccess(): bool
    {
        if (!Auth::check()) return false;
        return UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::UltimateConsole);
    }

    public function getSystemStats()
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();

        $globalMessage = Redis::get('system:global_message');
        $redisStatus = ['connected' => false, 'ping_ms' => null, 'used_memory_human' => null, 'version' => null, 'error' => null];

        try {
            $start = microtime(true);
            $pong = Redis::ping();
            $redisStatus['ping_ms'] = round((microtime(true) - $start) * 1000, 2);
            $redisStatus['connected'] = in_array($pong, [true, 'PONG', '+PONG'], true) || (is_string($pong) && stripos($pong, 'PONG') !== false);
            $info = Redis::info();
            if (is_array($info)) {
                $flat = isset($info['Memory']) ? $info['Memory'] : $info;
                $redisStatus['used_memory_human'] = $flat['used_memory_human'] ?? null;
                $serverInfo = isset($info['Server']) ? $info['Server'] : $info;
                $redisStatus['version'] = $serverInfo['redis_version'] ?? null;
            }
        } catch (\Throwable $e) {
            $redisStatus['error'] = $e->getMessage();
        }

        $stats = [
            'users'              => User::count(),
            'active_users'       => User::where('active', true)->count(),
            'residents'          => DB::table('barangay_residents')->count(),
            'households'         => DB::table('barangay_households')->count(),
            'blotters'           => DB::table('barangay_blotters')->count(),
            'document_requests'  => DB::table('barangay_document_requests')->count(),
            'projects'           => DB::table('barangay_projects')->count(),
            'announcements'      => DB::table('announcements')->count(),
            'php_version'        => PHP_VERSION,
            'server_time'        => date('Y-m-d H:i:s'),
            'maintenance_mode'   => Redis::get('system:maintenance_mode') === 'true',
            'global_message'     => $globalMessage ? json_decode($globalMessage, true) : null,
            'logs_count'         => DB::table('logs')->count(),
            'table_logs_count'   => DB::table('table_logs')->count(),
            'redis'              => $redisStatus,
        ];

        return Response::json(['success' => true, 'data' => $stats]);
    }

    public function runQuery(Request $request)
    {
        if (Auth::user()->acct_type !== UserTypes::SUPER_ADMIN || !UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::UltimateQuery)) {
            return ResponseHelper::returnUnauthorized();
        }

        $query = $request->input('query');
        if (empty($query)) return ResponseHelper::returnError('Query cannot be empty');

        $lower = strtolower(trim($query));
        $allowed = str_starts_with($lower, 'select') || str_starts_with($lower, 'show') || str_starts_with($lower, 'describe') || str_starts_with($lower, 'explain');
        if (!$allowed) {
            return ResponseHelper::returnError('Only SELECT, SHOW, DESCRIBE, EXPLAIN queries are allowed');
        }

        try {
            $results = DB::select($query);
            return Response::json(['success' => true, 'data' => $results, 'count' => count($results)]);
        } catch (\Throwable $e) {
            return ResponseHelper::returnError('Query error: ' . $e->getMessage());
        }
    }

    public function setMaintenanceMode(Request $request)
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
        $enabled = (bool) $request->input('enabled', false);
        Redis::set('system:maintenance_mode', $enabled ? 'true' : 'false');
        return Response::json(['success' => true, 'maintenance_mode' => $enabled]);
    }

    public function setGlobalMessage(Request $request)
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
        $message = $request->input('message');
        if ($message) {
            Redis::set('system:global_message', json_encode([
                'text'       => $message,
                'type'       => $request->input('type', 'info'),
                'updated_at' => now()->toDateTimeString(),
            ]));
        } else {
            Redis::del('system:global_message');
        }
        return Response::json(['success' => true]);
    }

    public function clearCache(Request $request)
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
        Redis::flushDB();
        return Response::json(['success' => true, 'message' => 'Cache cleared']);
    }

    public function getLogs(Request $request)
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
        $limit = min((int) $request->input('limit', 50), 200);
        $logs = DB::table('logs')->orderByDesc('id')->limit($limit)->get();
        return Response::json(['success' => true, 'data' => $logs]);
    }

    public function getTableLogs(Request $request)
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
        $limit = min((int) $request->input('limit', 50), 200);
        $logs = DB::table('table_logs')->orderByDesc('id')->limit($limit)->get();
        return Response::json(['success' => true, 'data' => $logs]);
    }

    public function backupDatabase(Request $request)
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();

        $name = $request->input('name', 'backup_' . date('Y_m_d_His'));
        $backup = DbBackup::create([
            'name'       => $name,
            'status'     => 'pending',
            'created_by' => Auth::id(),
        ]);

        return Response::json(['success' => true, 'data' => $backup, 'message' => 'Backup queued']);
    }

    public function listBackups()
    {
        if (!$this->checkAccess()) return ResponseHelper::returnUnauthorized();
        $backups = DbBackup::orderByDesc('id')->limit(20)->get();
        return Response::json(['success' => true, 'data' => $backups]);
    }
}
