<?
$encryptionSeparator = chr(31); // 31 de ASCII (Separador de Unidades)
$encryptionPadding   = chr(29); // 29 de ASCII (Separador de Grupos)

function error($code = 500, $msg = "Unknown Error") {
    http_response_code($code);
    session_write_close();
    die($msg);
};

function removePadding($encoded) {
    global $encryptionPadding;
    
    $paddingReplacement = $encryptionPadding; // ASCII group separator
    return rtrim($encoded, '=') . str_repeat($paddingReplacement, strlen($encoded) % 4);
}

function restorePadding($encoded, $paddingReplacement) {
    return rtrim($encoded, $paddingReplacement) . str_repeat('=', strlen($encoded) % 4);
}

function shortEncode($string, $key = "3162..,") {
    $compressed = gzcompress($string, 9); // Compress the string
    $encrypted = openssl_encrypt($compressed, 'AES-256-ECB', $key); // Encrypt the compressed data
    $encrypted = removePadding($encrypted);
    return $encrypted;
}

function shortDecode($encrypted, $key = "3162..,") {
    global $encryptionSeparator, $encryptionPadding;

    $encrypted = str_replace(" ", "+", $encrypted);
    $encrypted = restorePadding($encrypted, $encryptionPadding);
    $decrypted = openssl_decrypt($encrypted, 'AES-256-ECB', $key); // Decrypt the data
    $decompressed = gzuncompress($decrypted); // Decompress the data
    return explode($encryptionSeparator, $decompressed);
}

function setOptionalParamsKeys($data) {
    $optional = [
        "user_id"	   => $data[0],
        "plate_number" => $data[1],
        "plan_id"      => $data[2],
        "period"       => $data[3],
        "period_type"  => $data[4]
    ];

    return $optional;
}

function getPaymentByToken($token) {
    //Prepara el arreglo de datos
    $params = [
        "token" => $token
    ];
    //Define el metodo a usar
    $serviceName = "payment/getStatus";

    try {
        // Instancia la clase FlowApi
        $flowApi     = new FlowApi();
        // Ejecuta el servicio
        $payment     = $flowApi->send($serviceName, $params, "GET");

        return $payment;
    } catch (Exception $e) {
        echo $e->getCode() . " - " . $e->getMessage();
    }
}

function getPaymentByFlowOrder($order): array {
    //Prepara el arreglo de datos
    $params = [
        "flowOrder" => $order
    ];
    //Define el metodo a usar
    $serviceName = "payment/getStatusByFlowOrder";

    try {
        // Instancia la clase FlowApi
        $flowApi     = new FlowApi();
        // Ejecuta el servicio
        $payment     = $flowApi->send($serviceName, $params, "GET");

        return [
            "flowOrder" => $payment["flowOrder"],
            "status" => $payment["status"],
            "optional" => $payment["optional"]
        ];
    } catch (Exception $e) {
        echo $e->getCode() . " - " . $e->getMessage();
    }
}

function getPendingPayments($mysqli): array {
    $query = "SELECT
                flow_order
            FROM gs_user_billing_plans
            WHERE payment_status = 1";
    
    if ($stmt = mysqli_prepare($mysqli, $query)) {

        mysqli_stmt_bind_result($stmt, $flowOrder);
        
        mysqli_stmt_execute($stmt);

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        $pendingPayments = [];

        while (mysqli_stmt_fetch($stmt)) {
            
            $payment = getPaymentByFlowOrder($flowOrder);
            array_push($pendingPayments, $payment);
        }

        mysqli_stmt_close($stmt);

        return $pendingPayments;
    }
}

function getPlans($mysqli) {
    $query = "SELECT
                plan_id,
                period,
                period_type,
                name,
                price
            FROM gs_billing_plans
            WHERE active = 'true'
            ORDER BY plan_id";

    $plans = [];

    if ($stmt = mysqli_prepare($mysqli, $query)) {
        
        try {

            mysqli_stmt_execute($stmt);
            
            $res = mysqli_stmt_get_result($stmt);

            while ($plan = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
                array_push($plans, $plan);
            }

        } catch (Exception $e) {
            error(500, $e->getCode() . " - " . $e->getMessage());
        }

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        mysqli_stmt_close($stmt);
        return $plans;
    }
}

function getUserByEmail($mysqli, $email) {
    $query = "SELECT
                id
            FROM gs_users
            WHERE email = ?";
    
    if ($stmt = mysqli_prepare($mysqli, $query)) {
        
        try {
            
            mysqli_stmt_bind_param(
                $stmt,
                "s",
                $email
            );

            mysqli_stmt_execute($stmt);
            
            $res = mysqli_stmt_get_result($stmt);
            
            $user = mysqli_fetch_array($res, MYSQLI_ASSOC);

        } catch (Exception $e) {
            error(500, $e->getCode() . " - " . $e->getMessage());
        }

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        mysqli_stmt_close($stmt);

        return $user;
    }
}

function getObjectByPlateNumber($mysqli, $plateNumber) {
    $query = "SELECT
                imei
            FROM gs_objects
            WHERE plate_number = ?";
    
    if ($stmt = mysqli_prepare($mysqli, $query)) {
        
        try {
            
            mysqli_stmt_bind_param(
                $stmt,
                "s",
                $plateNumber
            );

            mysqli_stmt_execute($stmt);
            
            $res = mysqli_stmt_get_result($stmt);
            
            $object = mysqli_fetch_array($res, MYSQLI_ASSOC);

        } catch (Exception $e) {
            error(500, $e->getCode() . " - " . $e->getMessage());
        }

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        mysqli_stmt_close($stmt);

        return $object;
    }
}

function insertPayment($mysqli, $payment): int {
    $inserted = 0;
    
    $optional    = shortDecode($payment["optional"]["Firma"]);
    $optional    = setOptionalParamsKeys($optional);
    $paymentData = $payment["paymentData"];

    $object      = getObjectByPlateNumber($mysqli, $optional['plate_number']);

    $period      = $optional["period"];
    $periodType  = $optional["period_type"];

    $userId      = +$optional["user_id"];
    $paymentDate = $payment["requestDate"];
    $subject     = $payment["subject"];
    $objects     = 1;
    $amount      = +$payment["amount"];
    $flowOrder   = +$payment["flowOrder"];
    $status      = +$payment["status"];
    $imei        = $object["imei"];
    $email       = $payment["payer"];

    $sql = "INSERT IGNORE INTO gs_user_billing_plans (
                user_id,
                dt_purchase,
                name,
                objects,
                period,
                period_type,
                price,
                flow_order,
                payment_status,
                imei,
                email
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    if ($stmt = mysqli_prepare($mysqli, $sql)) {
        
        try {
            mysqli_stmt_bind_param(
                $stmt,
                "issiisdiiss",
                $userId,
                $paymentDate,
                $subject,
                $objects,
                $period,
                $periodType,
                $amount,
                $flowOrder,
                $status,
                $imei,
                $email
            );
        } catch (Exception $e) {
            error(500, $e);
        }
        
        mysqli_stmt_execute($stmt);

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        $inserted = mysqli_stmt_affected_rows($stmt);
        
        mysqli_stmt_close($stmt);
    } else {
        error(500, "Error: ".mysqli_error($mysqli));
    }

    return $inserted;
}


function updatePayment($mysqli, $payment): int {
    $updated     = 0;

    $status      = +$payment["status"];
    $flowOrder   = +$payment["flowOrder"];
    $date        = $payment["date"] ?? false;

    $updateDate  = $date ? ",dt_purchase    = ?" : "";
    
    $sql = "UPDATE gs_user_billing_plans
            SET
                payment_status = ?
                {$updateDate}
            WHERE 1 = 1
                AND flow_order = ?";

    if ($stmt = mysqli_prepare($mysqli, $sql)) {
        
        try {
            if ($date) {

                mysqli_stmt_bind_param(
                    $stmt,
                    "isi",
                    $status,
                    $date,
                    $flowOrder
                );
            } else {

                mysqli_stmt_bind_param(
                    $stmt,
                    "ii",
                    $status,
                    $flowOrder
                );
            }
        } catch (Exception $e) {
            error(500, $e);
        }

        mysqli_stmt_execute($stmt);

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        $updated = mysqli_stmt_affected_rows($stmt);
        
        mysqli_stmt_close($stmt);
    } else {
        error(500, "Error: ".mysqli_error($mysqli));
    }

    return $updated;
}

function updateObject($mysqli, $payload): int {
    $updated      = 0;
    
    $plateNumber = $payload["plate_number"];
    $period       = +$payload["period"];
    $periodType   = $payload["period_type"];
    $flowOrder = +$payload["flowOrder"];

    $sql = "CALL st_add_plan_to_object(?, ?, ?, ?);";
                            

    if ($stmt = mysqli_prepare($mysqli, $sql)) {
        
        try {
            mysqli_stmt_bind_param(
                $stmt,
                "issi",
                $period,
                $periodType,
                $plateNumber,
                $flowOrder
            );
        } catch (Exception $e) {
            error(500, $e->getCode() . " - " . $e->getMessage());
        }

        mysqli_stmt_execute($stmt);

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        $updated = mysqli_stmt_affected_rows($stmt);
        
        mysqli_stmt_close($stmt);
    } else {
        error(500, "Error: ".mysqli_error($mysqli));
    }

    return $updated;
}

function annulPendingPayments($mysqli): int {
    $deleted = 0;
    
    $query = "UPDATE gs_user_billing_plans
                SET payment_status = 4
                WHERE 1 = 1
                    AND payment_status = 1
                    AND DATEDIFF(SYSDATE(), dt_purchase) >= 1";
    
    if ($stmt = mysqli_prepare($mysqli, $query)) {

        mysqli_stmt_execute($stmt);

        if (mysqli_stmt_errno($stmt)) {
            error(500, "Error: ".mysqli_stmt_error($stmt));
        }

        $deleted = mysqli_stmt_affected_rows($stmt);

        mysqli_stmt_close($stmt);

    } else {
        error(500, "Error: ".mysqli_error($mysqli));
    }
    
    return $deleted;
}