<?php

namespace App\Controllers;

use App\Core\Controller;
use App\Models\Config;
use App\Config\SiteConfig;
use App\Libraries\RouterOSAPI;
use App\Helpers\EncryptionHelper;
use App\Helpers\FormatHelper;

class PublicStatusController extends Controller {

    // View: Show Search Page
    public function index($session) {
        // Just verify session existence to display Hotspot Name
        // Session verified by RouterCheckMiddleware
        $configModel = new Config();
        $creds = $configModel->getSession($session);

        $data = [
            'session' => $session,
            'hotspot_name' => $creds['hotspot_name'] ?? 'Hotspot',
            'footer_text' => SiteConfig::getFooter()
        ];

        return $this->view('public/status', $data);
    }

    // API: Check Status
    public function check($codeUrl = null) {
        header('Content-Type: application/json');

        // Allow POST and GET
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' && $_SERVER['REQUEST_METHOD'] !== 'GET') {
            http_response_code(405);
            echo json_encode(['error' => 'Method Not Allowed']);
            return;
        }

        $input = json_decode(file_get_contents('php://input'), true) ?? [];
        
        // Session: Try Body -> Try Header
        $session = $input['session'] ?? '';
        if (empty($session)) {
            $headers = getallheaders();
            // Handle case-insensitivity of headers
            $session = $headers['X-Mivo-Session'] ?? ($headers['x-mivo-session'] ?? '');
        }
        
        // Code: Can be in URL or Body
        $code = $codeUrl ?? ($input['code'] ?? '');

        if (empty($session) || empty($code)) {
            http_response_code(400);
            echo json_encode(['error' => 'Session and Voucher Code are required']);
            return;
        }

        $configModel = new Config();
        $creds = $configModel->getSession($session);

        if (!$creds) {
            http_response_code(404);
            echo json_encode(['error' => 'Session not found']);
            return;
        }

        $password = $creds['password'];
        if (isset($creds['source']) && $creds['source'] === 'legacy') {
            $password = RouterOSAPI::decrypt($password);
        }

        $api = new RouterOSAPI();
        if (!$api->connect($creds['ip'], $creds['user'], $password)) {
             http_response_code(500);
             echo json_encode(['error' => 'Router Connection Failed']);
             return;
        }

        // Logic Refactor: Pivot to User Table as primary source for Voucher Details
        // 1. Check User in Database
        $user = $api->comm("/ip/hotspot/user/print", [
            "?name" => $code
        ]);

        if (!empty($user)) {
            $u = $user[0];
            
            // --- SECURITY CHECK: Hide Unused Vouchers ---
            $uptimeRaw = $u['uptime'] ?? '0s';
            $bytesIn = intval($u['bytes-in'] ?? 0);
            $bytesOut = intval($u['bytes-out'] ?? 0);
            
            if (($uptimeRaw === '0s' || empty($uptimeRaw)) && ($bytesIn + $bytesOut) === 0) {
                 $api->disconnect();
                 echo json_encode(['success' => false, 'message' => 'Voucher Not Found']); 
                 return;
            }

            // --- SECURITY CHECK: Hide Unlimited Members ---
            $limitBytes = isset($u['limit-bytes-total']) ? intval($u['limit-bytes-total']) : 0;
            $limitUptime = $u['limit-uptime'] ?? '0s';

            if ($limitBytes === 0 && ($limitUptime === '0s' || empty($limitUptime))) {
                 // Option: Allow checking them but show minimalistic info, or hide. 
                 // Sticking to original logic: Hide them.
                 $api->disconnect();
                 echo json_encode(['success' => false, 'message' => 'Voucher Not Found']); 
                 return;
            }

            // --- CALCULATIONS ---
            $dataUsed = $bytesIn + $bytesOut;
            $dataLeft = 'Unlimited';
            
            if ($limitBytes > 0) {
                $remaining = max(0, $limitBytes - $dataUsed);
                $dataLeft = ($remaining === 0) ? '0 B' : FormatHelper::formatBytes($remaining);
            }

            // Validity Logic
            $validityRaw = $u['limit-uptime'] ?? '0s';
            $validityDisplay = ($validityRaw === '0s') ? 'Unlimited' : FormatHelper::elapsedTime($validityRaw);
            $expiration = '-';
            
            $comment = strtolower($u['comment'] ?? '');
            if (preg_match('/exp\W+([a-z]{3}\/\d{2}\/\d{4}\s\d{2}:\d{2}:\d{2})/', $comment, $matches)) {
                 $expiration = $matches[1]; 
            } elseif ($validityRaw !== '0s') {
                 $totalSeconds = FormatHelper::parseDuration($validityRaw);
                 $usedSeconds = FormatHelper::parseDuration($uptimeRaw);
                 $remainingSeconds = max(0, $totalSeconds - $usedSeconds);
                 
                 if ($remainingSeconds > 0) {
                     $expiration = date('d M Y H:i', time() + $remainingSeconds);
                 } else {
                     $expiration = 'Expired';
                 }
            }

            // BASE STATUS
            $status = 'offline';
            $statusLabel = 'Valid / Offline';
            $isDisabled = ($u['disabled'] ?? 'false') === 'true';

            // Calculate Time Left
            $timeLeft = 'Unlimited';
            if ($expiration !== '-' && $expiration !== 'Expired') {
                $expTime = strtotime($expiration);
                if ($expTime) {
                    $rem = max(0, $expTime - time());
                    $timeLeft = ($rem === 0) ? 'Expired' : FormatHelper::formatSeconds($rem);
                }
            } elseif ($validityRaw !== '0s') {
                $totalSeconds = FormatHelper::parseDuration($validityRaw);
                $usedSeconds = FormatHelper::parseDuration($uptimeRaw);
                $rem = max(0, $totalSeconds - $usedSeconds);
                $timeLeft = ($rem === 0) ? 'Expired' : FormatHelper::formatSeconds($rem);
            }
            
            if (strpos($comment, 'exp') !== false || ($expiration === 'Expired')) {
                $status = 'expired';
                $statusLabel = 'Expired';
            } elseif ($limitBytes > 0 && $dataUsed >= $limitBytes) {
                $status = 'limited';
                $statusLabel = 'Quota Exceeded';
            } elseif ($isDisabled) {
                $status = 'locked';
                $statusLabel = 'Locked / Disabled';
            }

            // 2. CHECK ACTIVE OVERRIDE
            // If user is conceptually valid (or even if limited?), check if they are currently active
            // Because they might be active BUT expiring soon, or active BUT over quota (if server hasn't kicked them yet)
            $active = $api->comm("/ip/hotspot/active/print", [
                "?user" => $code
            ]);

            if (!empty($active)) {
                $status = 'active';
                $statusLabel = 'Active (Online)';
            }

            $data = [
                'status' => $status,
                'status_label' => $statusLabel,
                'username' => $u['name'] ?? 'Unknown',
                'profile' => $u['profile'] ?? 'default',
                'uptime_used' => FormatHelper::elapsedTime($uptimeRaw),
                'validity' => $validityDisplay,
                'data_used' => FormatHelper::formatBytes($dataUsed),
                'data_left' => $dataLeft,
                'expiration' => $expiration,
                'time_left' => $timeLeft,
                'comment' => $u['comment'] ?? '',
            ];
            
            echo json_encode(['success' => true, 'data' => $data]);
            $api->disconnect();
            return;
        }

        // 3. Fallback: Check Active Only (Trial Users or IP Bindings not in User Table)
        $active = $api->comm("/ip/hotspot/active/print", [
            "?user" => $code
        ]);

        if (!empty($active)) {
            $u = $active[0];
            $data = [
                'status' => 'active',
                'status_label' => 'Active (Online)',
                'username' => $u['user'] ?? 'Unknown',
                'profile' => '-', // Active usually doesn't have profile name directly unless queried
                'uptime_used' => FormatHelper::elapsedTime($u['uptime'] ?? '0s'),
                'validity' => '-',
                'data_used' => FormatHelper::formatBytes(intval($u['bytes-in'] ?? 0) + intval($u['bytes-out'] ?? 0)),
                'data_left' => 'Unknown',
                'time_left' => isset($u['session-time-left']) ? FormatHelper::elapsedTime($u['session-time-left']) : '-',
                'expiration' => '-',
                'comment' => ''
            ];
            echo json_encode(['success' => true, 'data' => $data]);
            $api->disconnect();
            return;
        }

        $api->disconnect();
        echo json_encode(['success' => false, 'message' => 'Voucher Not Found']);
    }
}
