<?php
// Enable errors only for CLI or debugging
if (php_sapi_name() === 'cli') {
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
}


// ---- Input ----
$mac   = isset($_GET['mac'])   ? trim($_GET['mac'])   : '';
$devinfo  = isset($_GET['devinfo'])  ? trim($_GET['devinfo'])  : '';
$uname = isset($_GET['uname']) ? trim($_GET['uname']) : '';
$pword = isset($_GET['pword']) ? trim($_GET['pword']) : '';


// ---- JSON header ----
if (!headers_sent()) {
    header('Content-Type: application/json; charset=UTF-8');
}


if (!isset($_GET['uname'])) {
    echo json_encode(['status' => false, 'error' => 'No username provided']);
    exit;
}


// -------------------------------------------------------------------
// STEP 1: Create a SINGLE database connection at the beginning
// -------------------------------------------------------------------
try {
    $db = new SQLite3(__DIR__ . '/.db.db', SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
    $db->busyTimeout(5000);
    
    // ✅ Performance optimization
    $db->exec("PRAGMA journal_mode = WAL;");
    $db->exec("PRAGMA synchronous = NORMAL;");
    $db->exec("PRAGMA temp_store = MEMORY;");
    $db->exec("PRAGMA cache_size = 10000;");
} catch (Exception $e) {
    header('Content-Type: application/json');
    http_response_code(500);
    echo json_encode(['error' => 'Database connection failed.']);
    exit;
}

paneluser(
    preload($db, $_GET['uname'] ?? '', $_GET['pword'] ?? '', $_GET['mac'] ?? ''),
    $db,
    $_GET['uname'] ?? '',
    $_GET['pword'] ?? '',
    $_GET['mac'] ?? '',
    $_GET['devinfo'] ?? ''
);

$db->close();

function paneluser($jsondata,SQLite3 $db ,string $uname, string $pword,string $mac, string $devinfo){
    $data = json_decode($jsondata, true);

    if (!is_array($data)) {
        return "Invalid JSON";
    }

    $maxdev_qty = isset($data['maxdev_qty']) ? intval($data['maxdev_qty']) : 0;
    $alrady_dev = isset($data['alrady_dev']) ? $data['alrady_dev'] : false;


    if ($alrady_dev === false) {
        if ($maxdev_qty === 0) {
            outecho(4,0,$db,$uname,$pword,$mac,$devinfo); //error_max_dev
            return;
        }else if($maxdev_qty === 100997){
            outecho(5,0,$db,$uname,$pword,$mac,$devinfo); //error_no_user
            return;
        } elseif ($maxdev_qty == 1970) {
            checkusers(0, $db , $uname, $pword, $mac, $devinfo); //sucsess no limit
            return;
        } else {
            checkusers(1,$db, $uname, $pword, $mac, $devinfo); //sucsess reduse max device
            return;
        }
    }else{
        checkusers(0,$db, $uname, $pword, $mac, $devinfo); //allrady user device
        return;
    }

}

function checkusers(int $prestatus, SQLite3 $db, string $uname, string $pword, string $mac, string $devinfo): int {
    $devun = strtolower(trim($uname));
    $devpw = strtolower(trim($pword));

    $stmt = $db->prepare('SELECT id, title, username, password, expire_date, blok 
                          FROM menualusers 
                          WHERE LOWER(username) = :username AND LOWER(password) = :password');

    if ($stmt === false) {
        error_log('checkusers: prepare() failed');
        outecho(3, 0, $db,$uname,$pword,$mac,$devinfo);
        return 3;
    }

    $stmt->bindValue(':username', $devun, SQLITE3_TEXT);
    $stmt->bindValue(':password', $devpw, SQLITE3_TEXT);
    $result = $stmt->execute();

    if ($result === false) {
        error_log('checkusers: execute() failed');
        $stmt->close();
        outecho(3, 0, $db,$uname,$pword,$mac,$devinfo);
        return 3;
    }

    $row = $result->fetchArray(SQLITE3_ASSOC);
    $result->finalize();
    $stmt->close();

    if (!$row) {
        outecho(3, 0, $db,$uname,$pword,$mac,$devinfo);
        return 3;
    }

    $username = $row['username'] ?? '';
    $password = $row['password'] ?? '';
    $isBlocked = intval($row['blok'] ?? 0);
    $expired  = $row['expire_date'] ?? '';
    

    $expiryTimestamp = strtotime($expired ?? '');
    $isExpired = ($expiryTimestamp && time() <= $expiryTimestamp) ? 1 : 0;

    if ($devun === strtolower($username) && $devpw === strtolower($password) && $isExpired >= 1 && $isBlocked != 1) {
        outecho(1, $prestatus, $db,$uname,$pword,$mac,$devinfo);
        return 1;
    } elseif ($isExpired === 0) {
        outecho(2, $prestatus, $db,$uname,$pword,$mac,$devinfo);
        return 2;
    } elseif($isBlocked === '1'){
        outecho(6, $prestatus, $db,$uname,$pword,$mac,$devinfo);
        return 6;
    } else {
        outecho(3, 0, $db,$uname,$pword,$mac,$devinfo);
        return 3;
    }
}

function preload(SQLite3 $db, string $uname, string $pword, string $mac){
    $data = array(
    "maxdev_qty" => getmaxdevice($db,$uname,$pword),
    "alrady_dev" => checkdevices($db,$uname,$pword,$mac),
    "used_dev" => checkdevicesqty($db,$uname,$pword));
    return json_encode($data, JSON_UNESCAPED_UNICODE);
}

function getmaxdevice(SQLite3 $db, string $uname, string $pword): int {
    // normalize
    $uname = strtolower(trim($uname));
    $pword = strtolower(trim($pword));

    // prepare
    $stmt = $db->prepare('SELECT rquota FROM menualusers WHERE LOWER(username) = :username AND LOWER(password) = :password');
    if ($stmt === false) {
        // prepare failed
        error_log('getmaxdevice: prepare failed');
        return 0;
    }

    $stmt->bindValue(':username', $uname, SQLITE3_TEXT);
    $stmt->bindValue(':password', $pword, SQLITE3_TEXT);

    $result = $stmt->execute();
    if ($result === false) {
        // execute failed
        $stmt->close();
        error_log('getmaxdevice: execute failed');
        return 0;
    }

    $device = null;
    if ($row = $result->fetchArray(SQLITE3_ASSOC)) {
        // cast to int safely
        $device = isset($row['rquota']) ? (int)$row['rquota'] : 0;
    } else {
        // username/password not matched
        $result->finalize();
        $stmt->close();
        return 100997; // special code as in your original logic (use int for strict comparisons)
    }

    // cleanup
    $result->finalize();
    $stmt->close();

    return $device;
}

function minusmaxdevice(SQLite3 $db, string $uname, string $pword, string $mac, string $devinfo): int {
    $uname = strtolower(trim($uname));
    $pword = strtolower(trim($pword));

    $stmt = $db->prepare('SELECT rquota FROM menualusers WHERE LOWER(username) = :username AND LOWER(password) = :password');
    if ($stmt === false) {
        error_log('minusmaxdevice: prepare failed');
        return 0;
    }

    $stmt->bindValue(':username', $uname, SQLITE3_TEXT);
    $stmt->bindValue(':password', $pword, SQLITE3_TEXT);
    $result = $stmt->execute();
    if ($result === false) {
        error_log('minusmaxdevice: execute failed');
        $stmt->close();
        return 0;
    }

    $device = 0;
    $row = $result->fetchArray(SQLITE3_ASSOC);
    if ($row && isset($row['rquota'])) {
        $device = (int)$row['rquota'];
    }

    $result->finalize();
    $stmt->close();

    if ($device > 0) {
        $newDevice = max(0, $device - 1);

        // Optional: Transaction safety
        try {
        $db->exec('BEGIN IMMEDIATE TRANSACTION');

        $update = $db->prepare('UPDATE menualusers 
                                SET rquota = :newDevice 
                                WHERE LOWER(username) = :username 
                                AND LOWER(password) = :password');
        if ($update !== false) {
            $update->bindValue(':newDevice', $newDevice, SQLITE3_INTEGER);
            $update->bindValue(':username', $uname, SQLITE3_TEXT);
            $update->bindValue(':password', $pword, SQLITE3_TEXT);
            $update->execute();
            $update->close();
        }

        $db->exec('COMMIT');

        } catch (Exception $e) {
            $db->exec('ROLLBACK');
            error_log('minusmaxdevice transaction failed: ' . $e->getMessage());
        }

        if (function_exists('savenewdevices')) {
            savenewdevices($db, $uname, $pword, $mac, $devinfo);
        }

        return $newDevice;
    }

    return $device;
}

function checkdevices(SQLite3 $db, string $uname, string $pword, string $mac): bool {
    // Normalize and sanitize inputs
    $uname = strtolower(trim($uname));
    $pword = strtolower(trim($pword));
    $mac   = strtolower(trim($mac));

    // Prepare statement safely
    $stmt = $db->prepare('SELECT 1 FROM derec WHERE LOWER(uname) = :uname AND LOWER(pass) = :pass AND LOWER(mac) = :mac LIMIT 1');
    if ($stmt === false) {
        error_log('checkdevices: Failed to prepare statement');
        return false;
    }

    // Bind values
    $stmt->bindValue(':uname', $uname, SQLITE3_TEXT);
    $stmt->bindValue(':pass',  $pword, SQLITE3_TEXT);
    $stmt->bindValue(':mac',   $mac,   SQLITE3_TEXT);

    // Execute query
    $result = $stmt->execute();
    if ($result === false) {
        $stmt->close();
        error_log('checkdevices: Failed to execute statement');
        return false;
    }

    // Fetch result
    $exists = false;
    if ($row = $result->fetchArray(SQLITE3_ASSOC)) {
        $exists = true;
    }

    // Cleanup properly
    $result->finalize();
    $stmt->close();

    return $exists;
}

function checkdevicesqty(SQLite3 $db, string $uname, string $pword): int {
    // Normalize inputs
    $uname = strtolower(trim($uname));
    $pword = strtolower(trim($pword));

    // Prepare query safely
    $stmt = $db->prepare('SELECT COUNT(*) AS cnt FROM derec WHERE LOWER(uname) = :uname AND LOWER(pass) = :pass');
    if ($stmt === false) {
        error_log('checkdevicesqty: prepare() failed');
        return 0;
    }

    $stmt->bindValue(':uname', $uname, SQLITE3_TEXT);
    $stmt->bindValue(':pass',  $pword, SQLITE3_TEXT);

    // Execute safely
    $result = $stmt->execute();
    if ($result === false) {
        error_log('checkdevicesqty: execute() failed');
        $stmt->close();
        return 0;
    }

    // Fetch count
    $count = 0;
    if ($row = $result->fetchArray(SQLITE3_ASSOC)) {
        $count = isset($row['cnt']) ? (int)$row['cnt'] : 0;
    }

    // Cleanup
    $result->finalize();
    $stmt->close();

    return $count;
}

function savenewdevices(SQLite3 $db, string $uname, string $pword, string $mac, string $devinfo): int {
    $devun   = strtolower(trim($uname));
    $devpw   = strtolower(trim($pword));
    $devmac  = strtolower(trim($mac));
    $devinfo = strtolower(trim($devinfo));

    if ($devun === '' || $devpw === '' || $devmac === '') {
        error_log('savenewdevices: Missing required data');
        return 0;
    }

    // Check if already exists
    $chk = $db->prepare('SELECT 1 FROM derec WHERE LOWER(uname) = :uname AND LOWER(pass) = :pass AND LOWER(mac) = :mac LIMIT 1');
    if ($chk === false) {
        error_log('savenewdevices: prepare check failed');
        return 0;
    }

    $chk->bindValue(':uname', $devun, SQLITE3_TEXT);
    $chk->bindValue(':pass',  $devpw, SQLITE3_TEXT);
    $chk->bindValue(':mac',   $devmac, SQLITE3_TEXT);
    $chkRes = $chk->execute();

    if ($chkRes === false) {
        error_log('savenewdevices: execute check failed');
        $chk->close();
        return 0;
    }

    if ($chkRes->fetchArray(SQLITE3_NUM)) {
        // already exists
        $chkRes->finalize();
        $chk->close();
        return 0;
    }

    $chkRes->finalize();
    $chk->close();

    // Insert new record
    $stmt = $db->prepare('INSERT INTO derec (mac, uname, pass, df) VALUES (:mac, :uname, :pass, :df)');
    if ($stmt === false) {
        error_log('savenewdevices: prepare insert failed');
        return 0;
    }

    $stmt->bindValue(':mac',   $devmac, SQLITE3_TEXT);
    $stmt->bindValue(':uname', $devun,  SQLITE3_TEXT);
    $stmt->bindValue(':pass',  $devpw,  SQLITE3_TEXT);
    $stmt->bindValue(':df',    $devinfo,SQLITE3_TEXT);

    $result = $stmt->execute();

    if ($result) {
        $result->finalize();
        $stmt->close();
        return 1;
    }

    $stmt->close();
    return 0;
}

function outecho(int $status, int $dbhandle, ?SQLite3 $db = null,string $uname, string $pword,string $mac, string $devinfo) {
    $response = [];

    $base_server = [
        "url" => "rtxrebrand.com",
        "port" => "25443",
        "https_port" => "25463",
        "server_protocol" => "http",
        "rtmp_port" => "25444",
        "timezone" => "Europe/Athens",
        "timestamp_now" => time(),
        "time_now" => date('Y-m-d H:i:s')
    ];

    $user_base = [
        "username" => $uname,
        "password" => $pword,
        "exp_date" => "1733238335",
        "is_trial" => "0",
        "active_cons" => "0",
        "created_at" => "1668783935",
        "max_connections" => "1",
        "allowed_output_formats" => ["m3u8", "ts"]
    ];

    switch ($status) {
        case 1:
            $user_info = array_merge($user_base, [
                "message" => "",
                "auth" => 1,
                "status" => "Active"
            ]);
            break;
        case 2:
            $user_info = array_merge($user_base, [
                "message" => "",
                "auth" => 0,
                "status" => "Expired"
            ]);
            break;
        case 3:
            $user_info = array_merge($user_base, [
                "message" => "Username or Password are incorrect",
                "auth" => 0,
                "status" => "Username or Password are incorrect"
            ]);
            break;
        case 4:
            $user_info = array_merge($user_base, [
                "message" => "You have reached your maximum device limit.",
                "auth" => 0,
                "status" => "You have reached your maximum device limit."
            ]);
            break;
        case 5:
            $user_info = array_merge($user_base, [
                "message" => "Your user name cannot be found.",
                "auth" => 0,
                "status" => "Your user name cannot be found."
            ]);
            break;
        case 6:
            $user_info = array_merge($user_base, [
                "message" => "User blocked.",
                "auth" => 0,
                "status" => "User blocked."
            ]);
            break;    
        default:
            $response = ["error" => "Invalid status"];
            break;
    }

    if (!isset($response["error"])) {
        $response = [
            "user_info" => $user_info,
            "server_info" => $base_server
        ];
    }

    if ($dbhandle == 1 && $db instanceof SQLite3 && function_exists('minusmaxdevice')) {
        try {
            $db->busyTimeout(5000);
            minusmaxdevice($db, $uname, $pword, $mac, $devinfo);
        } catch (Throwable $t) {
            error_log('minusmaxdevice() failed: ' . $t->getMessage());
        }
    }


    if (!headers_sent()) {
        header('Content-Type: application/json; charset=UTF-8');
    }

    echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}


?>