<?php
include(__DIR__ . '/table.php');

// =======================
// CONFIG
// =======================
try {
    @$config_ini = parse_ini_file(__DIR__ . "/config.ini");
} catch (Exception $e) {
    @$config_ini = parse_ini_file(__DIR__ . "/../config.ini");
}

// =======================
// DEBUG MODE
// =======================
if (!empty($config_ini['debug']) && $config_ini['debug'] == 1) {
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    error_reporting(E_ALL);
} else {
    ini_set('display_errors', 0);
}

// =======================
// SESSION
// =======================
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// =======================
// CSRF TOKEN
// =======================
function generate_token() {
    if (!isset($_SESSION["ftg"])) {
        $_SESSION["ftg"] = bin2hex(random_bytes(32));
    }
    return $_SESSION["ftg"];
}

// =======================
// SQLITE DB PATH (ABSOLUTE)
// =======================
$dbPath = __DIR__ . '/../api/.db.db';

// =======================
// CREATE TABLES
// =======================
function createTables($tables, $dbLoc) {
    $db = new SQLite3($dbLoc);

    foreach ($tables as $tableName => $columns) {
        $sql = "CREATE TABLE IF NOT EXISTS $tableName (";
        foreach ($columns as $columnName => $columnType) {
            $sql .= "$columnName $columnType, ";
        }
        $sql = rtrim($sql, ', ') . ");";
        $db->exec($sql);
    }
    $db->close();
}

createTables($tables, $dbPath);

// =======================
// SQLITE WRAPPER
// =======================
class SQLiteWrapper {
    private $db;

    public function __construct($dbLoc) {
        $this->db = new SQLite3($dbLoc);
    }

    public function select($table, $columns = "*", $where = "", $order = "", $params = []) {
        $sql = "SELECT $columns FROM $table";
        if ($where) $sql .= " WHERE $where";
        if ($order) $sql .= " ORDER BY $order";

        $stmt = $this->db->prepare($sql);
        foreach ($params as $k => $v) {
            $stmt->bindValue($k, $v);
        }

        $res = $stmt->execute();
        $rows = [];
        while ($row = $res->fetchArray(SQLITE3_ASSOC)) {
            $rows[] = $row;
        }
        return $rows;
    }

    public function insert($table, $data) {
        $cols = implode(',', array_keys($data));
        $vals = ':' . implode(',:', array_keys($data));
        $stmt = $this->db->prepare("INSERT INTO $table ($cols) VALUES ($vals)");
        foreach ($data as $k => $v) {
            $stmt->bindValue(":$k", $v);
        }
        return $stmt->execute();
    }

    public function update($table, $data, $where, $params = []) {
        $set = [];
        foreach ($data as $k => $v) {
            $set[] = "$k=:$k";
        }
        $stmt = $this->db->prepare("UPDATE $table SET " . implode(',', $set) . " WHERE $where");
        foreach ($data as $k => $v) {
            $stmt->bindValue(":$k", $v);
        }
        foreach ($params as $k => $v) {
            $stmt->bindValue($k, $v);
        }
        return $stmt->execute();
    }

    public function delete($table, $where, $params = []) {
        $stmt = $this->db->prepare("DELETE FROM $table WHERE $where");
        foreach ($params as $k => $v) {
            $stmt->bindValue($k, $v);
        }
        return $stmt->execute();
    }

    public function getLastInsertId() {
        return $this->db->lastInsertRowID();
    }
}

// =======================
// INIT DB (GLOBAL)
// =======================
$db = new SQLiteWrapper($dbPath);

// =======================
// CURRENT USER
// =======================
function getCurrentUser($db) {
    if (empty($_SESSION['user_id'])) {
        return false;
    }

    $user = $db->select(
        "users",
        "*",
        "id = :id",
        "",
        [":id" => $_SESSION['user_id']]
    );

    return $user ? $user[0] : false;
}

// =======================
// ENCRYPTION
// =======================
class Encryption {
    public static function run($input) {
        return strrev(bin2hex($input));
    }
}

// =======================
// CURL CALL
// =======================
class calllink {
    public static function run($url) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 5,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false
        ]);
        return json_decode(curl_exec($ch), true);
    }
}

// =======================
// REAL IP
// =======================
function real_ip() {
    foreach ([
        'HTTP_X_FORWARDED_FOR',
        'HTTP_CLIENT_IP',
        'REMOTE_ADDR'
    ] as $key) {
        if (!empty($_SERVER[$key])) {
            return htmlspecialchars($_SERVER[$key], ENT_QUOTES, 'UTF-8');
        }
    }
    return 'unknown';
}
// =======================
// ROLE LABEL (PT-BR)
// =======================
function role_label_ptbr($role) {
    $map = [
        'master'         => 'MASTER',
        'super-reseller' => 'SUPER REVENDEDOR',
        'reseller'       => 'REVENDEDOR',
        'client'         => 'CLIENTE',
    ];
    $role = (string)$role;
    return $map[$role] ?? strtoupper($role);
}



// =======================
// CREDITS / TEAM HELPERS
// =======================
function is_unlimited_credits($value) {
    if ($value === null) return false;
    $value = is_string($value) ? trim(strtolower($value)) : $value;
    return $value === 'unlimited' || $value === '∞' || (is_numeric($value) && (int)$value < 0);
}

function normalize_credits_value($value, $allowUnlimited = false) {
    if ($allowUnlimited && (isset($value['unlimited']) || $value === 'unlimited' || $value === '∞' || $value === '-1' || $value === -1)) {
        return -1;
    }
    $intValue = (int)$value;
    return max(0, $intValue);
}

function credits_display($value) {
    return is_unlimited_credits($value) ? '∞' : number_format((int)$value, 0, ',', '.');
}

function build_in_clause_params(array $values, $prefix = ':p') {
    $params = [];
    $parts = [];
    $i = 0;
    foreach ($values as $value) {
        $key = $prefix . $i;
        $parts[] = $key;
        $params[$key] = $value;
        $i++;
    }
    return [
        'sql' => $parts ? implode(',', $parts) : '',
        'params' => $params
    ];
}

function get_direct_children(SQLiteWrapper $db, $username) {
    $rows = $db->select('menualuser', 'username', 'parent = :p', 'username ASC', [':p' => $username]);
    return array_values(array_map(function($row){ return $row['username']; }, $rows));
}

function get_visible_client_owners(SQLiteWrapper $db, $role, $username) {
    if ($role === 'master') {
        return [];
    }
    if ($role === 'super-reseller') {
        $owners = [$username];
        foreach (get_direct_children($db, $username) as $child) {
            $owners[] = $child;
        }
        return array_values(array_unique($owners));
    }
    return [$username];
}

function ensure_codes_schema($dbFile) {
    if (!file_exists($dbFile)) {
        return;
    }
    $sqlite = new SQLite3($dbFile);
    $columns = [];
    $result = @$sqlite->query("PRAGMA table_info(codes)");
    if ($result) {
        while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
            $columns[] = $row['name'];
        }
    }
    $wanted = [
        'client_name' => "ALTER TABLE codes ADD COLUMN client_name TEXT",
        'client_whatsapp' => "ALTER TABLE codes ADD COLUMN client_whatsapp TEXT",
        'status' => "ALTER TABLE codes ADD COLUMN status TEXT DEFAULT 'active'",
        'is_free_trial' => "ALTER TABLE codes ADD COLUMN is_free_trial INTEGER DEFAULT 0",
        'trial_hours' => "ALTER TABLE codes ADD COLUMN trial_hours INTEGER DEFAULT 0",
        'client_ip' => "ALTER TABLE codes ADD COLUMN client_ip TEXT",
        'device_id' => "ALTER TABLE codes ADD COLUMN device_id TEXT",
    ];
    foreach ($wanted as $name => $sql) {
        if (!in_array($name, $columns, true)) {
            @$sqlite->exec($sql);
        }
    }
    @$sqlite->close();
}

// =======================
// SETTINGS (CHAVE/VALOR)
// =======================
function settings_get($db, $key, $default = null) {
    try {
        $rows = $db->select('settings', 'value', 'key = :k', '', [':k' => (string)$key]);
        if ($rows && array_key_exists('value', $rows[0])) {
            return $rows[0]['value'];
        }
    } catch (Throwable $e) {
        // ignore
    }
    return $default;
}

function settings_set($db, $key, $value) {
    $key = (string)$key;
    $value = (string)$value;
    try {
        $rows = $db->select('settings', 'key', 'key = :k', '', [':k' => $key]);
        if ($rows) {
            return $db->update('settings', ['value' => $value], 'key = :k', [':k' => $key]);
        }
        return $db->insert('settings', ['key' => $key, 'value' => $value]);
    } catch (Throwable $e) {
        return false;
    }
}
