<?php
include('config.php');
require_once 'request.php';
date_default_timezone_set('Asia/Tehran');
#-----------------------------#
function token_panel($code_panel){
    // پشتیبانی از هم id و هم code_panel (مانند freemirza که از id استفاده می‌کند)
    $panel = select("marzban_panel","*","id",$code_panel,"select");
    if (!is_array($panel) || empty($panel)) {
        $panel = select("marzban_panel","*","code_panel",$code_panel,"select");
    }
    if (!is_array($panel) || empty($panel)) {
        return ["error" => "Panel configuration not found"];
    }
    
    // دقیقاً مانند freemirza
    if($panel['datelogin'] != null){
        $date = json_decode($panel['datelogin'],true);
        if(isset($date['time'])){
            $timecurrent = time();
            $start_date = time() - strtotime($date['time']);
            if($start_date <= 3600){
                return $date;
            }
        }
    }
    $url_get_token = $panel['url_panel'].'/api/admin/token';
    $data_token = array(
        'username' => $panel['username_panel'],
        'password' => $panel['password_panel']
    );
    $options = array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_TIMEOUT_MS => 6000,
        CURLOPT_POSTFIELDS => http_build_query($data_token),
        CURLOPT_HTTPHEADER => array(
            'Content-Type: application/x-www-form-urlencoded',
            'accept: application/json'
        )
    );
    $curl_token = curl_init($url_get_token);
    curl_setopt_array($curl_token, $options);
    $token = curl_exec($curl_token);
    if (curl_error($curl_token)) {
        $token = [];
        $token['errror'] = curl_error($curl_token);
        return $token;
    }
    curl_close($curl_token);

    $body = json_decode( $token, true);
    if(isset($body['access_token'])){
        $time = date('Y/m/d H:i:s');
        $data = json_encode(array(
            'time' => $time,
            'access_token' => $body['access_token']
            ));
        update("marzban_panel","datelogin",$data,'name_panel',$panel['name_panel']);
    }
    return $body;
}
#-----------------------------#

function findMarzbanPanelByName($location)
{
    $panel = select("marzban_panel", "*", "name_panel", $location, "select");
    if (!is_array($panel) || empty($panel)) {
        return null;
    }

    return $panel;
}
#-----------------------------#

function getuser($username_account,$location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/' . $username_account;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}
#-----------------------------#

function Get_Nodes($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/nodes';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}
function Get_usage_Nodes($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/nodes/usage';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}
function Get_Node($location,$Nodeid)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$Nodeid;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}

function getusers($location,$status)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/users?status='.$status;
    if(!isset($Check_token['access_token']))return;
    $header_value = 'Bearer ';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value .  $Check_token['access_token']
    ));

    $output = curl_exec($ch);
    curl_close($ch);
    $data_user = json_decode($output, true);

    if (!is_array($data_user)) {
        return ['error' => 'Unable to decode panel response.'];
    }

    if (isset($data_user['error'])) {
        return $data_user;
    }

    if (!isset($data_user['users'])) {
        $data_user['users'] = [];
    }

    return $data_user;
}
#-----------------------------#
function getinbounds($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/inbounds';
    $header_value = 'Bearer ';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value .  $Check_token['access_token']
    ));

    $output = curl_exec($ch);
    curl_close($ch);
    $inbounds = json_decode($output, true);
    return $inbounds;
}
#-----------------------------#
function ResetUserDataUsage($username_account,$location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/' . $username_account.'/reset';

    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->post(array());
    return $response;
}
function revoke_sub($username_account,$location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/' . $username_account.'/revoke_sub';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->post(array());
    return $response;
}
#-----------------------------#
// تابع adduser با signature مشابه freemirza برای سازگاری
function adduser($username, $expire, $data_limit, $location, $is_test = false)
{
    // اگر با signature قدیمی صدا زده شد، پارامترها را تبدیل می‌کنیم
    if (func_num_args() > 5) {
        // signature قدیمی: $location,$data_limit,$username_ac,$timestamp,$note ='',$data_limit_reset = 'no_reset',$name_product = false
        $args = func_get_args();
        $location = $args[0];
        $data_limit = $args[1];
        $username = $args[2];
        $expire = $args[3];
        $note = isset($args[4]) ? $args[4] : '';
        $data_limit_reset = isset($args[5]) ? $args[5] : 'no_reset';
        $name_product = isset($args[6]) ? $args[6] : false;
        $is_test = ($name_product == "usertest");
    }
    
    global $pdo, $new_marzban;
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return json_encode(["detail" => "Panel configuration not found"]);
    }
    
    // استفاده از id برای token_panel (مانند freemirza)
    $Check_token = token_panel($marzban_list_get['id'] ?? $marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return json_encode(["detail" => $Check_token['error']]);
    }
    
    $url = $marzban_list_get['url_panel']."/api/user";
    $header_value = 'Bearer ';
    
    // Ensure default groups exist for newer Marzban versions (>0.8.4)
    if (function_exists('ensure_default_groups')) {
        ensure_default_groups($location);
    }
    
    // ساخت data دقیقاً مانند freemirza
    $data = array(
        "proxies" => json_decode($marzban_list_get['proxies']),
        "data_limit" => $data_limit,
        "username" => $username
    );
    
    // Add group assignment for Marzban >0.8.4 using group_ids
    if (function_exists('is_marzban_version_above_084') && is_marzban_version_above_084($location)) {
        $group_name = $is_test ? "mirza_test" : "mirza_paid";
        if (function_exists('get_groups')) {
            $groups = get_groups($location);
            $group_id = null;
            if (is_array($groups) && isset($groups['groups'])) {
                foreach ($groups['groups'] as $group) {
                    if (isset($group['name']) && $group['name'] === $group_name && isset($group['id'])) {
                        $group_id = $group['id'];
                        break;
                    }
                }
            }
            if ($group_id !== null) {
                $data['group_ids'] = array($group_id);
            }
        }
    }
    
    if($marzban_list_get['inbounds'] != null and $marzban_list_get['inbounds'] != "null"){
        $data['inbounds'] = json_decode($marzban_list_get['inbounds'],true);
    }
    
    // پردازش expire دقیقاً مانند freemirza
    if($expire == "0"){
        $data['expire'] = 0;
    }else {
        if(isset($marzban_list_get['onholdstatus']) && $marzban_list_get['onholdstatus'] == "ononhold"){
            $data["expire"] = 0;
            $data["status"] = "on_hold";
            $data["on_hold_expire_duration"] = $expire - time();
        }else{
            $data['expire'] = $expire;
        }
    }
    
    $payload = json_encode($data);
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value .  $Check_token['access_token'],
        'Content-Type: application/json'
    ));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    return $response;
}
//----------------------------------
function Get_System_Stats($location){
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/system';
    $header_value = 'Bearer ';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Accept: application/json',
        'Authorization: ' . $header_value .  $Check_token['access_token']
    ));

    $output = curl_exec($ch);
    curl_close($ch);
    $Get_System_Stats = json_decode($output, true);
    return $Get_System_Stats;
}
//----------------------------------
function removeuser($location,$username)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/'.$username;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->delete();
    return $response;
}
function removenode($location,$nodeid){
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$nodeid;
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->delete();
    return $response;
}
//----------------------------------
function Modifyuser($location,$username,array $data)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/user/'.$username;
    $headers = array(
            'accept: application/json',
            'Content-Type: application/json'
    );
    $payload = json_encode($data);
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->put($payload);
    return $response;
}
//----------------------------------

function Modifyuser_node($location,$id_node,array $data)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$id_node;
    $payload = json_encode($data);
    $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Authorization: Bearer '.$Check_token['access_token'];
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
curl_close($ch);
     $data_useer = json_decode($result, true);
    return $data_useer;
}
function hosts($location)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    $url =  $marzban_list_get['url_panel'].'/api/hosts';
    $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$headers = array();
$headers[] = 'Accept: application/json';
$headers[] = 'Authorization: Bearer '.$Check_token['access_token'];
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
curl_close($ch);
     $data_hosts = $result;
    return $data_hosts;
}
//----------------------------------
function reconnect_node($location,$id_node)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel'].'/api/node/'.$id_node.'/reconnect';
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->post(array());
    return $response;
}

function get_list_update($location,$username)
{
    $marzban_list_get = findMarzbanPanelByName($location);
    if ($marzban_list_get === null) {
        return ["error" => "Panel configuration not found for the requested location."];
    }
    $Check_token = token_panel($marzban_list_get['code_panel']);
    if(!empty($Check_token['error'])){
        return $Check_token;
    }
    $url =  $marzban_list_get['url_panel']."/api/user/$username/sub_update?offset=0&limit=1";
    $headers = array(
            'accept: application/json'
    );
    $req = new CurlRequest($url);
    $req->setHeaders($headers);
    $req->setBearerToken($Check_token['access_token']);
    $response = $req->get();
    return $response;
}