<?php

namespace api\classes;

use api\classes\API;
use JetBrains\PhpStorm\NoReturn;

require_once 'API.php';

class API_inserve extends API
{

    private string $inserve_url;

    private string $inserve_token;

    public string $inserve_source_uuid;

    public array $inserve_custom_data;

    private $ch;

    public $httpCode = false;

    public $response = false;

    private $cloudDistributor = false;

    public function setupConnection()
    {
        $query = "SELECT * FROM system_sources WHERE source_name = 'inserve'";
        $result = $this->conn->query($query)->fetch_assoc();

        $this->inserve_url = $result['source_url'];
        $this->inserve_token = $result['source_auth_token'];
        $this->inserve_source_uuid = $result['source_uuid'];
        $this->inserve_custom_data = json_decode($result['source_custom_data'], 1)['data'];
    }

    public function execCurl()
    {
        $this->response = curl_exec($this->ch);
        $this->httpCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);

        curl_close($this->ch);
    }

    public function authMe()
    {
        $this->ch = curl_init($this->inserve_url . 'auth/me');
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json"
            ]
        ]);
        $this->execCurl();
        return true;
    }

    public function getLinkedCompanies()
    {
        # init the cloudDistributor name
        if (!isset($this->inserve_custom_data['cloudDistributor']) || $this->inserve_custom_data['cloudDistributor'] === '') {
            $this->apiOutput(400, ['error' => 'missing cloudDistributor in custom source data']);
        } else {
            $this->cloudDistributor = $this->inserve_custom_data['cloudDistributor'];
        }

        $this->ch = curl_init($this->inserve_url . 'cloud-distributors/' . $this->cloudDistributor . '/companies');
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json"
            ]
        ]);
        $this->execCurl();
    }

    public function getProducts()
    {
        $this->ch = curl_init($this->inserve_url . 'products/');
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json"
            ]
        ]);
        $this->execCurl();
    }

    public function companies($page)
    {
        // Build array the way the API expects
        $params = [
            'b' => [
                ['orderBy' => ['name', 'ASC']],
                ['orderBy' => ['id', 'DESC']],
                ['with' => ['operator', 'country']],
                ['paginate' => 300],
            ],
            'page' => $page
        ];

        $query = http_build_query($params);

        $this->ch = curl_init($this->inserve_url . 'companies?' . $query);

        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json"
            ]
        ]);

        $this->execCurl();

        return json_decode($this->response, true);
    }


    public function syncCompaniesFromSentri()
    {
        # init the cloudDistributor name

        if (!isset($this->inserve_custom_data['cloudDistributor']) || $this->inserve_custom_data['cloudDistributor'] === '') {
            $this->apiOutput(400, ['error' => 'missing cloudDistributor in custom source data']);
        } else {
            $this->cloudDistributor = $this->inserve_custom_data['cloudDistributor'];
        }

        # First retrieve all the active companies to sync to the Inserve cloud distributor
        $companies = [];

        $sql = "SELECT company_source_id FROM companies WHERE company_state = 'active'";
        $stmt = $this->conn->query($sql);
        while ($row = $stmt->fetch_assoc()) {
            $id = (int)$row['company_source_id'];
            $companies[] = [
                'cloud_distribution_id' => (string)$id,
                'company_id' => $id
            ];
        }

        $url = $this->inserve_url . 'cloud-distributors/' . $this->cloudDistributor . '/companies';

        $this->ch = curl_init($url);

        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($companies),
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json",
                "Content-Type: application/json"
            ],
        ]);

        $this->execCurl();
    }

    public function getCloudSubscriptions()
    {

        $this->ch = curl_init($this->inserve_url . 'cloud-distribution-subscriptions/');

        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json"
            ]
        ]);

        $this->execCurl();
    }

    public function getSubscriptions()
    {

        $this->ch = curl_init($this->inserve_url . 'subscriptions/');

        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json"
            ]
        ]);

        $this->execCurl();
    }

    public function updateCloudSubscription($subscriptionId = false, $payload = false)
    {
        $url = $this->inserve_url . 'cloud-distribution-subscriptions/' . $subscriptionId;

        $this->ch = curl_init($url);

        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json",
                "Content-Type: application/json"
            ],
        ]);

        $this->execCurl();
    }

    public function updateSubscription($subscriptionId = false, $payload = false)
    {
        $url = $this->inserve_url . 'subscriptions/' . $subscriptionId;

        $this->ch = curl_init($url);

        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => 'PUT',
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json",
                "Content-Type: application/json"
            ],
        ]);

        $this->execCurl();
    }

    private function getAllTypes($type)
    {
        $allowedColumns = [
            'server_licenses',
            'server_backup'
        ];

        if (!in_array($type, $allowedColumns, true)) {
            throw new \RuntimeException('Invalid column name');
        }

        $query = "SELECT `$type` FROM servers";
        $stmt = $this->prepareStatement($query);
        $this->executeStatement($stmt);
        $result = $stmt->get_result();

        $servers = [];
        while ($row = $result->fetch_assoc()) {
            $servers[] = $row;
        }

        $allTypes = [];
        foreach ($servers as $server) {
            if (!empty($server[$type])) {
                $types = json_decode($server[$type], true);
                if (is_array($types)) {
                    foreach ($types as $item) {
                        foreach ($item as $key => $value) {
                            $allTypes[$key . '.' . $value] = 0;
                        }
                    }
                }
            }
        }
        return $allTypes;
    }

    private function calculateTotalDiskUsage($diskJson)
    {
        $disks = json_decode($diskJson, true);
        $server_disks_count = 0;
        if (is_array($disks)) {
            foreach ($disks as $disk) {
                $server_disks_count += $disk['disk_space'];
            }
        }
        if (is_array($disks) && count($disks) > 0) {
            $sizes = array_column($disks, 'disk_space');
            $server_disks_count = array_sum($sizes);
        }
        return $server_disks_count;
    }

    private function buildCountObject(string $serverUuid, string $key): array
    {
        return [
            'countSentri' => 0,
            'countInserve' => 0,
            'sentriCompanyId' => 0,
            'SentriStatus' => 0,
            'subscriptionInserveExists' => false,
            'subscriptionInserveId' => false,
            'subscriptionInserveCompanyId' => false,
            'subscriptionInserveName' => false,
            'subscriptionInserveStatus' => 0,
            'md5' => md5($serverUuid . ':' . $key),
        ];
    }

    private function transformTypes(array $types, string $serverUuid): array
    {
        $result = [];

        foreach ($types as $key => $value) {
            $result[$key] = $this->buildCountObject($serverUuid, $key);
        }

        return $result;
    }

    private function buildCountArray($serverUuid)
    {
        $allBackupTypes = $this->getAllTypes('server_backup');
        $allLicenseTypes = $this->getAllTypes('server_licenses');

        $backupCounts = $this->transformTypes($allBackupTypes, $serverUuid);
        $licenseCounts = $this->transformTypes($allLicenseTypes, $serverUuid);

        return array_merge(
            [
                "server_CPU_count" => $this->buildCountObject($serverUuid, 'server_cpu_count'),
                "server_Memory_count" => $this->buildCountObject($serverUuid, 'server_memory_count'),
                "server_Disk_space_count" => $this->buildCountObject($serverUuid, 'server_disks_count'),
            ],
            $licenseCounts,
            $backupCounts
        );

    }

    public function syncServerLicencesToInserve()
    {
        # Get all the linked companies
        $this->getLinkedCompanies();
        $allCompanies = json_decode($this->response, true);
        $allCompaniesIds = array_column($allCompanies['matched'], 'id', 'company_id');

        # first get the current subscriptions
        $this->getCloudSubscriptions();
        $allInserveCloudSubscriptions = json_decode($this->response, true);

        # Filter out all the none Sentri posted subscriptions based on the name for performance
        $allInserveCloudSubscriptions = array_filter($allInserveCloudSubscriptions, function ($subscription) {
            return isset($subscription['cloud_subscription_id']) && $subscription['cloud_subscription_id'] === 'sentri-servers';
        });

        # Build lookup of existing Inserve subscriptions by cloud_distribution_id
        # this will be used later to lookup
        $inserveLookup = [];
        foreach ($allInserveCloudSubscriptions as $subscription) {
            if (!empty($subscription['cloud_distribution_id'])) {
                $inserveLookup[$subscription['cloud_distribution_id']] = [
                    'id' => (int)$subscription['id'],
                    'quantity' => (int)$subscription['quantity'],
                    'status' => (int)$subscription['status'],
                    'cloud_distribution_company_id' => (int)$subscription['cloud_distribution_company_id'],
                    'name' => $subscription['name'],
                ];
            }
        }

        # get all the servers from Sentri
        $sql = "SELECT * FROM servers INNER JOIN companies ON servers.company_uuid = companies.company_uuid WHERE company_state = 'active' AND server_state != 'new' AND server_state != 'disabled' ";
        $stmt = $this->conn->query($sql);

        while ($row = $stmt->fetch_assoc()) {
            # Create a count of all the Subscriptions possible with every count on 0
            $subscriptionCounts = $this->buildCountArray($row['server_uuid']);
            $totalDiskSpace = $this->calculateTotalDiskUsage($row['server_disks']);

            # Inserve status codes are:
            # 0 = active, 1 = cancelled, 2 = pending, 3 = trial, 4 = on hold, 5 = removed
            $statusMap = [
                'active' => 0,
                'trial' => 3,
                'deleted' => 5,
            ];

            // if no states matched there is something terrifying wrong, call the ambulance!
            if (!isset($statusMap[$row['server_state']])) {
                exit;
            }
            $sentriStatus = $statusMap[$row['server_state']];

            # Set all the server resource counts from Sentri into the $subscriptionCounts
            $subscriptionCounts['server_CPU_count']['countSentri'] = $row['server_cpu'];
            $subscriptionCounts['server_Memory_count']['countSentri'] = (int)ceil($row['server_memory'] / 1024);
            $subscriptionCounts['server_Disk_space_count']['countSentri'] = $totalDiskSpace;

            $licenses = json_decode($row['server_licenses'], true);
            if (is_array($licenses)) {
                foreach ($licenses as $license) {
                    foreach ($license as $key => $LicenseType) {
                        $subscriptionCounts[$key . '.' . $LicenseType]['countSentri']++;
                    }
                }
            }

            $backups = json_decode($row['server_backup'], true);
            foreach ($backups as $backup) {
                foreach ($backup as $key => $BackupType) {
                    $subscriptionCounts[$key . '.' . $BackupType]['countSentri'] = $totalDiskSpace;
                }
            }

            # Mark subscriptions that already exist in Inserve
            foreach ($subscriptionCounts as $key => &$item) {
                if (!is_array($item) || !isset($item['md5'])) {
                    continue;
                }

                $md5 = (string)$item['md5'];

                if (isset($inserveLookup[$md5])) { # Subscription already exists in Inserve
                    $item['SentriStatus'] = $sentriStatus;
                    $item['sentriCompanyId'] = (int)$allCompaniesIds[$row['company_source_id']] ?? 0;
                    $item['subscriptionInserveExists'] = true;
                    $item['subscriptionInserveId'] = $inserveLookup[$item['md5']]['id'];
                    $item['countInserve'] = $inserveLookup[$item['md5']]['quantity'];
                    $item['subscriptionInserveCompanyId'] = $inserveLookup[$item['md5']]['cloud_distribution_company_id'];
                    $item['subscriptionInserveName'] = $inserveLookup[$item['md5']]['name'];
                    //$item['subscriptionInserveStatus'] = $inserveLookup[$item['md5']]['status'];
                } else { # Subscription does not exist in Inserve
                    $item['sentriCompanyId'] = (int)$allCompaniesIds[$row['company_source_id']] ?? 0;
                    $item['subscriptionInserveExists'] = false;
                    $item['subscriptionInserveId'] = false;
                    $item['countInserve'] = 0;
                    $item['subscriptionInserveCompanyId'] = false;
                }
            }
            unset($item);

            // Make the subscriptions names look nice and dandy.
            foreach ($subscriptionCounts as $key => &$item) {
                // Set server name
                $serverName = $row['server_hostname'] ?? $row['server_vm_host_name'] ?? 'Unknown';

                // remove server_ prefix and _count suffix
                $namePart = $key;
                if (str_starts_with($key, 'server_') && str_ends_with($key, '_count')) {
                    $namePart = substr($key, 7, -6);
                    $namePart = ucfirst($namePart);
                } // Handle keys with "."
                elseif (str_contains($key, '.')) {
                    [$first, $second] = explode('.', $key, 2);
                    if ($first === $second || strtolower($second) === 'yes') {
                        $namePart = ucfirst($first);
                    } else {
                        $namePart = ucfirst($first) . ' - ' . $second;
                    }
                } //Handle keys without . but with a space (example directadmin.Standard Discounted)
                elseif (str_contains($key, ' ')) {
                    // explode on first .
                    $parts = explode('.', $key, 2);
                    if (count($parts) === 2) {
                        $namePart = ucfirst($parts[0]) . ' - ' . $parts[1];
                    } else {
                        // Cap first word before first space
                        $spacePos = strpos($key, ' ');
                        $first = ucfirst(substr($key, 0, $spacePos));
                        $rest = substr($key, $spacePos + 1);
                        $namePart = $first . ' - ' . $rest;
                    }
                }

                $item['subscriptionSentriName'] = $serverName . ' - ' . $namePart;
            }
            unset($item);

            foreach ($subscriptionCounts as $key => $item) {
                // if subscriptionInserveExists but the countInserve is null skip creation
                if ($item['subscriptionInserveExists'] === false && (int)$item['countSentri'] === 0) {
                    continue;
                }

                // if subscriptionInserveExists is false create a new subscription
                if ($item['subscriptionInserveExists'] === false) {
                    $payload = [
                        "cloud_distribution_id" => $item['md5'], #md5 hash based on the server_uuid from sentri and the subscription name (e.g. server_cpu_count)
                        "cloud_subscription_id" => "sentri-servers", # Mark all the sentri-servers subscriptions so we can filter the subscriptions better
                        "name" => $item['subscriptionSentriName'],
                        "quantity" => ($row['server_state'] === 'deleted') ? 0 : $item['countSentri'],
                        "cloud_distributor" => $this->cloudDistributor,
                        "cloud_distribution_company_id" => $item['sentriCompanyId'], # this is generated by inserve
                        "status" => $item['SentriStatus'],
                        "period_type" => 0, # 0 = monthly, 1 = annual, 2 = one time cost
                        "start_date" => date('Y-m-d')
                    ];

                    $this->createCloudSubscription($payload);

                    continue;
                }

                // update the subscription if the countInserve and countSentri don't match
                // Or when sentriCompanyId and subscriptionInserveCompanyId don't match
                if ((
                        (int)$item['countInserve'] !== (int)$item['countSentri'] ||
                        (int)$item['sentriCompanyId'] !== (int)$item['subscriptionInserveCompanyId'] ||
                        (int)$item['SentriStatus'] !== (int)$item['subscriptionInserveStatus'] ||
                        $item['subscriptionSentriName'] !== $item['subscriptionInserveName']
                    )
                    && $item['subscriptionInserveExists'] !== false
                ) {
                    $payload = [
                        "quantity" => ($row['server_state'] === 'deleted') ? 0 : $item['countSentri'],
                        "cloud_distributor" => $this->cloudDistributor,
                        "cloud_distribution_company_id" => (int)$item['sentriCompanyId'],
                        "name" => $item['subscriptionSentriName'],
                        "status" => $item['SentriStatus']
                    ];

                    $this->updateCloudSubscription($item['subscriptionInserveId'], $payload);

                }
            }
        }
    }

    public function getSubscriptionsLines($subscriptionId)
    {

        $params = ['b' => [['where' => [0 => 'subscription_lines.subscription_id', 1 => $subscriptionId]]]];

        $query = http_build_query($params);

        $this->ch = curl_init($this->inserve_url . 'subscription-lines?' . $query);

        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json"
            ]
        ]);

        $this->execCurl();
    }

    private function buildSubscriptionLine($subscription_description, $productCode, $allInserveProducts)
    {
        return [
            'quantity' => 0,
            'product_code' => $productCode,
            'price' => $allInserveProducts[$productCode]['price_excl'],
            'description' => $subscription_description . ' ' . $allInserveProducts[$productCode]['product_name'],
        ];
    }

    public function syncServerSubscriptionsToInserve()
    {
        $SentriCustomData = $this->inserve_custom_data;

        # Get all the Product IDs from Inserve
        $this->getProducts();
        $allInserveProducts = array_column(json_decode($this->response, true), null, 'product_code');

        # Get all the current subscriptions
        $this->getSubscriptions();
        $allInserveSubscriptions = json_decode($this->response, true);

        # Filter out all the none Sentri posted subscriptions based on the name for performance
        $allInserveVPSSubscriptions = array_filter($allInserveSubscriptions, function ($subscription) {
            return isset($subscription['description']) && str_contains($subscription['description'], 'VPS - ');
        });

        # get all the servers from Sentri
        $sql = "SELECT * FROM servers INNER JOIN companies ON servers.company_uuid = companies.company_uuid WHERE company_state = 'active' AND server_state != 'new' AND server_state != 'disabled' AND server_state != 'deleted' ";
        $stmt = $this->conn->query($sql);

        while ($row = $stmt->fetch_assoc()) {
            # init server item loop
            $subscription_description = 'VPS - ' . (!empty($row['server_vm_host_name']) ? $row['server_vm_host_name'] : $row['server_hostname']);
            $firstDayCurrentMonth = date('Y-m-01');
            $firstDayPreviousMonth = date('Y-m-d', strtotime('first day of last month'));
            $missing = [];
            $invalidProductCode = [];
            $subscriptionLines = [
                'lines' => []
            ];
            $subscriptionFound = false;

            # standard server components with flat values
            foreach (['server_cpu', 'server_memory', 'server_disks'] as $serverComponent) {
                if ($row[$serverComponent] != NULL) {
                    if (!isset($SentriCustomData['subscriptions'][$serverComponent])) {
                        $missing[] = $serverComponent;
                    }

                    $productCode = $SentriCustomData['subscriptions'][$serverComponent]['product_code'] ?? null;

                    #if (!isset($allInserveProducts[$productCode])) {
                    #    $invalidProductCode[] = $serverComponent;
                    #}

                    $subscriptionLines['lines'][] = $this->buildSubscriptionLine($subscription_description, $productCode, $allInserveProducts);
                }
            }

            # server backups
            if ($row['server_backup'] != NULL) {
                $server_backup = json_decode($row['server_backup'], true);
                if (!empty($server_backup)) {
                    foreach ($server_backup as $backupItem) {
                        foreach ($backupItem as $key => $value) {
                            if (!isset($SentriCustomData['subscriptions']['server_backup'][$key])) {
                                $missing[] = $key;
                            }

                            $productCode = $SentriCustomData['subscriptions']['server_backup'][$key]['product_code'] ?? null;

                            $subscriptionLines['lines'][] = $this->buildSubscriptionLine($subscription_description, $productCode, $allInserveProducts);
                        }
                    }
                }
            }

            # server licenses
            if ($row['server_licenses'] != NULL) {
                $server_licenses = json_decode($row['server_licenses'], true);
                if (!empty($server_licenses)) {
                    foreach ($server_licenses as $LicenseItem) {
                        foreach ($LicenseItem as $key => $value) {
                            if (!isset($SentriCustomData['subscriptions']['server_licenses'][$key][$value])) {
                                $missing[] = $key;
                            }

                            $productCode = $SentriCustomData['subscriptions']['server_licenses'][$key][$value]['product_code'] ?? null;

                            $subscriptionLines['lines'][] = $this->buildSubscriptionLine($subscription_description, $productCode, $allInserveProducts);
                        }
                    }
                }
            }


            if (!empty($missing)) {
                $this->apiOutput(400, [
                    'error' => 'Missing subscription data for: ' . implode(', ', $missing)
                ]);
            }

            if (!empty($invalidProductCode)) {
                $this->apiOutput(400, [
                    'error' => 'Invalid product code for: ' . implode(', ', $invalidProductCode)
                ]);
            }

            # Check if the subscription already exists to decide if we need to update or create the subscription
            foreach ($allInserveVPSSubscriptions as $subscription) {
                if (isset($subscription['description']) && str_contains($subscription['description'], $subscription_description)) {
                    $subscriptionFound = $subscription['id'];
                    break;
                }
            }

            if ($subscriptionFound) {
                # subscription already exists, update information that is collected by Sentri (company and server usages)
                $subscriptionId = $subscriptionFound;
                $existingLines = [];
                $missingLines = [];

                # Get the subscription lines from the specific subscriptionId
                $this->getSubscriptionsLines($subscriptionId);
                $InserveSubscriptionsLines = json_decode($this->response, true);

                foreach ($InserveSubscriptionsLines as $item) {
                    $existingLines[$item['product_code']] = $item;
                }

                # Check if there are products that don't exist yet or have different descriptions
                foreach ($subscriptionLines['lines'] as $subscriptionLine) {
                    $product_code = $subscriptionLine['product_code'];

                    if (!isset($existingLines[$product_code])) {
                        $missingLines[] = $subscriptionLine;
                        continue;
                    }

                    # Update the description and label if they differ.
                    if ($existingLines[$product_code]['description'] !== $subscriptionLine['description']) {
                        $existingLines[$product_code]['description'] = $subscriptionLine['description'];
                        $existingLines[$product_code]['_label'] = $subscriptionLine['description'];
                    }
                }

                $subscriptionPayload = [
                    'company_id' => (int)$row['company_source_id'] ?? 0,
                    'relationships' => [
                        'lines' => array_values(array_merge($existingLines, $missingLines))
                    ]
                ];
                $this->updateSubscription($subscriptionId, $subscriptionPayload);
            } else {
                # create a new subscription
                $subscriptionPayload = [
                    'description' => $subscription_description,
                    'company_id' => (int)$row['company_source_id'] ?? 0,
                    'periods' => 1,
                    'period' => 'month',
                    'start_period' => $firstDayCurrentMonth,
                    'direct_debit' => 0,
                    'next_billing_date' => $firstDayPreviousMonth,
                    'billing_start_date' => $firstDayPreviousMonth,
                    'invoice_periods' => 1,
                    'invoice_separately' => true,
                    'invoice_setting_on_change' => 'system',
                    'relationships' => $subscriptionLines,
                ];

                $this->createSubscription($subscriptionPayload);
            }
        }
    }


    public function createSubscription($payload)
    {
        $url = $this->inserve_url . 'subscriptions';
        $this->ch = curl_init($url);

        # I need to make this pay load:
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json",
                "Content-Type: application/json"
            ],
        ]);

        $this->execCurl();
    }

    public function createCloudSubscription($payload)
    {
        $url = $this->inserve_url . 'cloud-distribution-subscriptions';
        $this->ch = curl_init($url);

        # I need to make this pay load:
        curl_setopt_array($this->ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($payload),
            CURLOPT_HTTPHEADER => [
                "X-Api-Key: $this->inserve_token",
                "Accept: application/json",
                "Content-Type: application/json"
            ],
        ]);

        $this->execCurl();
    }
}
