<?php

namespace App\Http\Livewire\Admin;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Livewire\Component;

class Log extends Component
{
    public $logContent = '';
    public $message = '';
    public $diskUsage = '';
    public $diskUsageClass = '';
    public $availableRam;
    public $availableRamClass;
    public $queueWorkers = [];
    public $queueWorkersCount = 0;
    public $reverbConnected = false;


    public function mount()
    {
        // Security check: user must be authenticated
        if (!Auth::check()) {
            abort(403, 'Unauthorized');
        }

        // Security check: activeProfileType must be 'App\Models\Admin'
        if (getActiveProfileType() !== 'Admin') {
            abort(403, 'Unauthorized');
        }

        // Security check: user must own the active profile
        $activeProfile = getActiveProfile();
        if (!$activeProfile) {
            abort(403, 'Unauthorized');
        }

        // CRITICAL SECURITY: Validate user has ownership/access to this profile
        \App\Helpers\ProfileAuthorizationHelper::authorize($activeProfile);

        // Load log content - support both daily (laravel-YYYY-MM-DD.log) and single (laravel.log) drivers
        $logPath = storage_path('logs/laravel-' . date('Y-m-d') . '.log');
        if (!file_exists($logPath)) {
            $logPath = storage_path('logs/laravel.log');
        }
        if (file_exists($logPath)) {
            $logLines = (int) timebank_config('admin_settings.log_lines', 100);
            $this->logContent = shell_exec("tail -n {$logLines} " . escapeshellarg($logPath));
            // Use tail output to check for warnings/errors (avoid file() which loads entire file into memory)
            $recentLines = explode("\n", $this->logContent ?? '');
            
            $messages = [];
            if (collect($recentLines)->contains(fn ($line) => stripos($line, 'WARNING') !== false)) {
                $messages[] = '<span class="font-bold text-orange-500">Warning</span> detected in the recent log output';
            }
            if (collect($recentLines)->contains(fn ($line) => stripos($line, 'ERROR') !== false)) {
                $messages[] = '<span class="font-bold text-red-500">Error</span> detected in the recent log output';
            }
            if (collect($recentLines)->contains(fn ($line) => stripos($line, 'CRITICAL') !== false)) {
                $messages[] = '<span class="font-bold text-red-500">Critical</span> issue detected in the recent log output';
            }            
            if (collect($recentLines)->contains(fn ($line) => stripos($line, 'ALERT') !== false)) {
                $messages[] = '<span class="font-bold text-red-500">Alert</span> detected in the recent log output - IMMEDIATE ACTION REQUIRED';
            }
            $this->message = implode('<br>', $messages);
        }

            // Get disk usage
            $free = disk_free_space("/");
            $total = disk_total_space("/");
            $used = $total - $free;
            $percent = $total > 0 ? round(($used / $total) * 100, 1) : 0;

            
            // Determine disk usage color class
            if ($percent > 90) {
                $this->diskUsageClass = 'text-red-500';
            } elseif ($percent > 75) {
                $this->diskUsageClass = 'text-orange-500';
            } else {
                $this->diskUsageClass = 'text-green-500';
            }

            $this->diskUsage = sprintf(
                '%s used of %s (%.1f%%)',
                $this->formatBytes($used),
                $this->formatBytes($total),
                $percent
            );



            // Get RAM memory information
            $meminfo = file_get_contents('/proc/meminfo');
            preg_match('/MemTotal:\s+(\d+)/', $meminfo, $matchesTotal);
            preg_match('/MemAvailable:\s+(\d+)/', $meminfo, $matchesAvailable);

            $totalKb = $matchesTotal[1] ?? 0;
            $availableKb = $matchesAvailable[1] ?? 0;
            $usedKb = $totalKb - $availableKb;

            $percentRam = $totalKb > 0 ? round(($usedKb / $totalKb) * 100, 1) : 0;

            $this->availableRam = sprintf(
                '%s used of %s (%.1f%%)',
                $this->formatBytes($usedKb * 1024),
                $this->formatBytes($totalKb * 1024),
                $percentRam
            );

            if ($percentRam > 90) {
                $this->availableRamClass = 'text-red-500';
            } elseif ($percentRam > 75) {
                $this->availableRamClass = 'text-orange-500';
            } else {
                $this->availableRamClass = 'text-green-500';
            }

            
            // Check running queue workers
            $queueWorkers = [];
            exec("ps aux | grep 'artisan queue:work' | grep -v grep", $output);
            foreach ($output as $line) {
                // Parse $line for more details
                $queueWorkers[] = $line;
            }
            $this->queueWorkers = $queueWorkers;
            $this->queueWorkersCount = count($queueWorkers);

            // Check Reverb server connection (example: check if port is open)           
            $reverbPort = env('REVERB_PORT', 6001);

            // Check Reverb server connection
            $reverbConnected = false;
            $connection = @fsockopen('127.0.0.1', $reverbPort, $errno, $errstr, 1);
            if ($connection) {
                $reverbConnected = true;
                fclose($connection);
            }

            $this->reverbConnected = $reverbConnected;


    }

    // Helper to format bytes
    public function formatBytes($bytes, $precision = 2)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $bytes = max($bytes, 0);
        $pow = $bytes > 0 ? floor(log($bytes) / log(1024)) : 0;
        $pow = min($pow, count($units) - 1);
        $bytes /= (1 << (10 * $pow));
        return round($bytes, $precision) . ' ' . $units[$pow];
    }

    public function downloadLog()
    {
        $logPath = storage_path('logs/laravel-' . date('Y-m-d') . '.log');
        if (!file_exists($logPath)) {
            $logPath = storage_path('logs/laravel.log');
        }
        if (file_exists($logPath)) {
            return response()->download($logPath, 'laravel-' . date('Y-m-d') . '.log');
        }

        session()->flash('error', 'Log file not found');
    }

    public function render()
    {
        $layout = Auth::check() ? 'app-layout' : 'guest-layout';
        return view('livewire.admin.log', [
            'layout' => $layout,
            'logContent' => $this->logContent,
            'message' => $this->message,
            'diskUsage' => $this->diskUsage,
            'diskUsageClass' => $this->diskUsageClass,
            'availableRam' => $this->availableRam,
            'availableRamClass' => $this->availableRamClass,
            'queueWorkers' => $this->queueWorkers,
            'queueWorkersCount' => $this->queueWorkersCount,
            'reverbConnected' => $this->reverbConnected,
        ]);
    }
}
