<?php

if (!defined('WHMCS')) {
    die('This file cannot be accessed directly');
}

require_once __DIR__ . '/lib/ApiClient.php';

function hexagamecloud_MetaData(): array
{
    return [
        'DisplayName' => 'HexaHost GameCloud',
        'APIVersion' => '1.1',
        'RequiresServer' => true,
        'DefaultNonSSLPort' => '443',
        'DefaultSSLPort' => '443',
    ];
}

function hexagamecloud_ConfigOptions(): array
{
    return [
        'plan_slug' => [
            'FriendlyName' => 'GameCloud Plan Slug',
            'Type' => 'text',
            'Size' => '32',
            'Default' => 'free',
            'Description' => 'Maps to a GameCloud plan slug',
        ],
        'minecraft_version' => [
            'FriendlyName' => 'Minecraft Version',
            'Type' => 'text',
            'Size' => '16',
            'Default' => '1.21.1',
        ],
        'software_family' => [
            'FriendlyName' => 'Software Family',
            'Type' => 'dropdown',
            'Options' => 'VANILLA,PAPER,PURPUR,FABRIC,FORGE,NEOFORGE,QUILT',
            'Default' => 'VANILLA',
        ],
    ];
}

function hexagamecloud_CreateAccount(array $params): string
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $externalClientId = (string) $params['clientsdetails']['userid'];
        $externalServiceId = (string) $params['serviceid'];

        $client->upsertClient($externalClientId, [
            'email' => $params['clientsdetails']['email'],
            'username' => $params['clientsdetails']['email'],
            'displayName' => trim(($params['clientsdetails']['firstname'] ?? '') . ' ' . ($params['clientsdetails']['lastname'] ?? '')),
        ]);

        $response = $client->provisionService([
            'externalServiceId' => $externalServiceId,
            'externalClientId' => $externalClientId,
            'externalProductId' => (string) ($params['pid'] ?? ''),
            'planSlug' => $params['configoption1'] ?: 'free',
            'serverName' => $params['domain'] ?: ('server-' . $externalServiceId),
            'minecraftVersion' => $params['configoption2'] ?: '1.21.1',
            'softwareFamily' => $params['configoption3'] ?: 'VANILLA',
            'edition' => 'JAVA',
            'eulaAccepted' => true,
        ]);

        return 'success';
    } catch (Throwable $exception) {
        logModuleCall(
            'hexagamecloud',
            __FUNCTION__,
            $params,
            $exception->getMessage(),
            $exception->getMessage(),
            ['password', 'secret', 'apiSecret']
        );
        return $exception->getMessage();
    }
}

function hexagamecloud_SuspendAccount(array $params): string
{
    return hexagamecloud_lifecycleAction($params, 'suspend', ['reason' => 'Suspended in WHMCS']);
}

function hexagamecloud_UnsuspendAccount(array $params): string
{
    return hexagamecloud_lifecycleAction($params, 'unsuspend');
}

function hexagamecloud_TerminateAccount(array $params): string
{
    return hexagamecloud_lifecycleAction($params, 'terminate');
}

function hexagamecloud_ChangePackage(array $params): string
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $client->changePackage((string) $params['serviceid'], [
            'planSlug' => $params['configoption1'] ?: 'free',
        ]);
        return 'success';
    } catch (Throwable $exception) {
        logModuleCall('hexagamecloud', __FUNCTION__, $params, $exception->getMessage());
        return $exception->getMessage();
    }
}

function hexagamecloud_ServiceSingleSignOn(array $params)
{
    return hexagamecloud_requestSso($params, 'service');
}

function hexagamecloud_AdminSingleSignOn(array $params)
{
    return hexagamecloud_requestSso($params, 'admin');
}

function hexagamecloud_TestConnection(array $params): array
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $health = $client->health();
        return [
            'success' => true,
            'error' => 'Connected to ' . ($health['integrationId'] ?? 'GameCloud'),
        ];
    } catch (Throwable $exception) {
        return ['success' => false, 'error' => $exception->getMessage()];
    }
}

function hexagamecloud_ListAccounts(array $params): array
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $response = $client->listAccounts();
        $accounts = [];

        foreach ($response['accounts'] ?? [] as $account) {
            $accounts[] = [
                'uuid' => $account['externalServiceId'] ?? '',
                'domain' => $account['domain'] ?? '',
                'username' => $account['username'] ?? '',
                'status' => $account['status'] ?? 'Active',
            ];
        }

        return $accounts;
    } catch (Throwable $exception) {
        logModuleCall('hexagamecloud', __FUNCTION__, $params, $exception->getMessage());
        return [];
    }
}

function hexagamecloud_MetricProvider(array $params)
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $serviceId = (string) $params['serviceid'];
        $usage = $client->getServiceUsage($serviceId, hexagamecloud_resolveUsageQuery($params));

        return [
            'metrics' => $usage['metrics'] ?? [],
        ];
    } catch (Throwable $exception) {
        logModuleCall('hexagamecloud', __FUNCTION__, $params, $exception->getMessage());
        return ['metrics' => []];
    }
}

function hexagamecloud_UsageUpdate(array $params)
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $serviceId = (string) $params['serviceid'];
        $usage = $client->getServiceUsage($serviceId, hexagamecloud_resolveUsageQuery($params));
        $usageUpdate = $usage['usageUpdate'] ?? [];

        return [
            'diskusage' => (float) ($usageUpdate['diskUsageGiB'] ?? 0),
            'bandwidth' => (float) ($usageUpdate['bandwidthGiB'] ?? 0),
        ];
    } catch (Throwable $exception) {
        logModuleCall('hexagamecloud', __FUNCTION__, $params, $exception->getMessage());
        return [
            'diskusage' => 0,
            'bandwidth' => 0,
        ];
    }
}

function hexagamecloud_resolveUsageQuery(array $params): array
{
    $query = [];

    if (!empty($params['usageperiodstart'])) {
        $query['periodStart'] = gmdate('c', strtotime((string) $params['usageperiodstart']));
    }

    if (!empty($params['usageperiodend'])) {
        $query['periodEnd'] = gmdate('c', strtotime((string) $params['usageperiodend']));
    }

    if (!empty($params['testmode']) || !empty($params['configoption4'])) {
        $query['testMode'] = true;
    }

    return $query;
}

function hexagamecloud_lifecycleAction(array $params, string $action, array $body = []): string
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $serviceId = (string) $params['serviceid'];
        if ($action === 'suspend') {
            $client->suspendService($serviceId, $body);
        } elseif ($action === 'unsuspend') {
            $client->unsuspendService($serviceId);
        } else {
            $client->terminateService($serviceId);
        }
        return 'success';
    } catch (Throwable $exception) {
        logModuleCall('hexagamecloud', $action, $params, $exception->getMessage());
        return $exception->getMessage();
    }
}

function hexagamecloud_requestSso(array $params, string $kind)
{
    try {
        $client = new HexaGameCloudApiClient($params);
        $externalServiceId = (string) $params['serviceid'];
        $externalClientId = (string) ($params['clientsdetails']['userid'] ?? $params['userid'] ?? '');
        $externalUserId = (string) ($params['clientsdetails']['userid'] ?? $params['adminid'] ?? $externalClientId);

        $response = $client->createServiceSso($externalServiceId, [
            'externalClientId' => $externalClientId,
            'externalUserId' => $externalUserId,
            'role' => $kind === 'admin' ? 'admin' : 'owner',
            'kind' => $kind,
        ]);

        return [
            'success' => true,
            'redirectTo' => $response['redirectUrl'],
        ];
    } catch (Throwable $exception) {
        logModuleCall('hexagamecloud', 'sso:' . $kind, $params, $exception->getMessage());
        return [
            'success' => false,
            'error' => $exception->getMessage(),
        ];
    }
}
