<?php
/**
 * WHMCS Product Addon Module for WHP AI Monitor
 *
 * Adds per-site AI-powered monitoring as a paid addon to existing WHP hosting products.
 * Hooks into the parent hosting service to communicate with the WHP server API.
 */

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

use WHMCS\Database\Capsule;

/**
 * Module configuration.
 *
 * Defines metadata and custom fields for the addon product.
 *
 * @return array
 */
function whp_ai_monitor_config()
{
    return array(
        'name'        => 'WHP AI Monitor',
        'description' => 'AI-powered monitoring for customer sites. Attaches to a WHP hosting product to enable per-site log analysis, issue detection, and alerting.',
        'version'     => '1.0',
        'author'      => 'WHP',
        'fields'      => array(
            'Monitored Site' => array(
                'Type'        => 'text',
                'Size'        => '64',
                'Default'     => '',
                'Description' => 'The site identifier (domain or site ID) on the WHP account to monitor',
            ),
        ),
    );
}

/**
 * Retrieve server connection details from the parent hosting service.
 *
 * Product addons are linked to a parent hosting service. This function looks up
 * the server assigned to that parent service and returns the connection details
 * needed to make API calls to the WHP server.
 *
 * @param array $params WHMCS addon module parameters
 * @return array|null Server data array or null if no server is found
 */
function whp_ai_monitor_getServerData(array $params)
{
    $serviceId = $params['serviceid'];

    // Use WHMCS localAPI to get the parent service details including server ID
    $result = localAPI('GetClientsProducts', array('serviceid' => $serviceId));
    $serverId = $result['products']['product'][0]['serverid'] ?? 0;

    if ($serverId) {
        $server = Capsule::table('tblservers')->where('id', $serverId)->first();
        if ($server) {
            return array(
                'hostname' => $server->hostname,
                'port'     => $server->port ?: '443',
                'secure'   => !empty($server->secure),
                'username' => decrypt($server->username), // API key
                'password' => decrypt($server->password), // API secret
            );
        }
    }

    return null;
}

/**
 * Get the WHP username from the parent hosting service.
 *
 * @param array $params WHMCS addon module parameters
 * @return string The WHP username on the parent hosting account
 */
function whp_ai_monitor_getWhpUsername(array $params)
{
    $serviceId = $params['serviceid'];
    $result = localAPI('GetClientsProducts', array('serviceid' => $serviceId));
    return $result['products']['product'][0]['username'] ?? '';
}

/**
 * Make an API call to the WHP server.
 *
 * Follows the same cURL pattern as the main WHP server module for consistency.
 *
 * @param array  $serverData Server connection details from whp_ai_monitor_getServerData()
 * @param string $endpoint   API endpoint path (appended to /api/external/)
 * @param string $method     HTTP method (GET, POST, PUT, DELETE)
 * @param array  $data       Request body data (will be JSON-encoded for POST/PUT/DELETE)
 * @return array Decoded JSON response
 * @throws Exception on cURL or HTTP errors
 */
function whp_ai_monitor_api_call(array $serverData, $endpoint, $method = 'GET', $data = null)
{
    $hostname  = $serverData['hostname'];
    $port      = $serverData['secure'] ? ($serverData['port'] ?: 443) : ($serverData['port'] ?: 80);
    $protocol  = $serverData['secure'] ? 'https' : 'http';
    $apiKey    = $serverData['username'];
    $apiSecret = $serverData['password'];

    if (empty($apiKey) || empty($apiSecret)) {
        $error = 'API credentials not configured on the parent service server';
        logModuleCall('whp_ai_monitor', 'api_call_error', $serverData, $error);
        throw new Exception($error);
    }

    $url = $protocol . '://' . $hostname . ':' . $port . '/api/external/' . $endpoint;

    logModuleCall('whp_ai_monitor', 'api_call_start', array(
        'url'    => $url,
        'method' => $method,
        'data'   => $data,
    ), 'Starting API call');

    $ch = curl_init();

    curl_setopt_array($ch, array(
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 30,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_USERAGENT      => 'WHMCS-WHP-AI-Monitor/1.0',
    ));

    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'X-Api-Key: ' . $apiKey,
        'X-Api-Secret: ' . $apiSecret,
    ));

    switch (strtoupper($method)) {
        case 'POST':
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
            break;

        case 'PUT':
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
            break;

        case 'DELETE':
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
            break;

        case 'GET':
        default:
            break;
    }

    $response  = curl_exec($ch);
    $httpCode  = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    $curlInfo  = curl_getinfo($ch);

    curl_close($ch);

    logModuleCall('whp_ai_monitor', 'api_call_response', array(
        'http_code'     => $httpCode,
        'curl_error'    => $curlError,
        'response_size' => strlen($response),
        'total_time'    => $curlInfo['total_time'],
    ), 'API call completed');

    if ($curlError) {
        $error = 'cURL Error: ' . $curlError;
        logModuleCall('whp_ai_monitor', 'curl_error', $curlInfo, $error);
        throw new Exception($error);
    }

    if ($httpCode >= 400) {
        $error = 'HTTP Error ' . $httpCode . ': ' . $response;
        logModuleCall('whp_ai_monitor', 'http_error', array(
            'code'     => $httpCode,
            'response' => $response,
        ), $error);
        throw new Exception($error);
    }

    $decodedResponse = json_decode($response, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        $error = 'Invalid JSON response: ' . json_last_error_msg() . ' - Raw: ' . $response;
        logModuleCall('whp_ai_monitor', 'json_error', array(
            'error'    => json_last_error_msg(),
            'response' => $response,
        ), $error);
        throw new Exception($error);
    }

    logModuleCall('whp_ai_monitor', $method . ' ' . $endpoint, $data, $decodedResponse);

    return $decodedResponse;
}

/**
 * Activate the AI monitoring addon.
 *
 * Called when the addon is provisioned (purchased or manually activated).
 * Registers the site for AI monitoring on the WHP server.
 *
 * @param array $params WHMCS addon module parameters
 * @return string 'success' or error message
 */
function whp_ai_monitor_Activate(array $params)
{
    try {
        $serverData = whp_ai_monitor_getServerData($params);

        if (!$serverData) {
            return 'Error: No server assigned to the parent hosting service. Cannot activate AI monitoring.';
        }

        $username = whp_ai_monitor_getWhpUsername($params);

        if (empty($username)) {
            return 'Error: Could not determine WHP username from the parent hosting service.';
        }

        // The monitored site is stored in the addon's custom field
        $siteId = $params['customfields']['Monitored Site'] ?? '';

        if (empty($siteId)) {
            return 'Error: No monitored site specified. Please set the "Monitored Site" custom field.';
        }

        logModuleCall('whp_ai_monitor', 'Activate', array(
            'username' => $username,
            'site_id'  => $siteId,
        ), 'Activating AI monitoring');

        $response = whp_ai_monitor_api_call($serverData, 'ai-monitor.php?action=activate', 'POST', array(
            'username' => $username,
            'site_id'  => $siteId,
        ));

        if (isset($response['status']) && $response['status'] === 'success') {
            return 'success';
        }

        $errorMsg = $response['message'] ?? 'Unknown error from WHP API';
        logModuleCall('whp_ai_monitor', 'Activate_Failed', $params, $errorMsg);
        return 'Error: ' . $errorMsg;

    } catch (Exception $e) {
        logModuleCall('whp_ai_monitor', __FUNCTION__, $params, $e->getMessage());
        return 'Error: ' . $e->getMessage();
    }
}

/**
 * Deactivate the AI monitoring addon.
 *
 * Called when the addon is cancelled or terminated.
 * Removes the site from AI monitoring on the WHP server.
 *
 * @param array $params WHMCS addon module parameters
 * @return string 'success' or error message
 */
function whp_ai_monitor_Deactivate(array $params)
{
    try {
        $serverData = whp_ai_monitor_getServerData($params);

        if (!$serverData) {
            return 'Error: No server assigned to the parent hosting service. Cannot deactivate AI monitoring.';
        }

        $username = whp_ai_monitor_getWhpUsername($params);

        if (empty($username)) {
            return 'Error: Could not determine WHP username from the parent hosting service.';
        }

        $siteId = $params['customfields']['Monitored Site'] ?? '';

        logModuleCall('whp_ai_monitor', 'Deactivate', array(
            'username' => $username,
            'site_id'  => $siteId,
        ), 'Deactivating AI monitoring');

        $response = whp_ai_monitor_api_call($serverData, 'ai-monitor.php?action=deactivate', 'POST', array(
            'username' => $username,
            'site_id'  => $siteId,
        ));

        if (isset($response['status']) && $response['status'] === 'success') {
            return 'success';
        }

        $errorMsg = $response['message'] ?? 'Unknown error from WHP API';
        logModuleCall('whp_ai_monitor', 'Deactivate_Failed', $params, $errorMsg);
        return 'Error: ' . $errorMsg;

    } catch (Exception $e) {
        logModuleCall('whp_ai_monitor', __FUNCTION__, $params, $e->getMessage());
        return 'Error: ' . $e->getMessage();
    }
}

/**
 * Render the Client Area output for the addon.
 *
 * Fetches current monitoring status from the WHP API and renders the
 * clientarea.tpl Smarty template with the data.
 *
 * @param array $params WHMCS addon module parameters
 * @return array Template data for WHMCS to render
 */
function whp_ai_monitor_ClientArea(array $params)
{
    try {
        $serverData = whp_ai_monitor_getServerData($params);

        if (!$serverData) {
            return array(
                'templatefile' => 'templates/clientarea',
                'vars'         => array(
                    'error'              => 'No server assigned to the parent hosting service.',
                    'monitoring_status'  => 'unknown',
                    'site_name'          => '',
                    'issue_count'        => 0,
                    'critical_count'     => 0,
                    'warning_count'      => 0,
                    'info_count'         => 0,
                    'dashboard_url'      => '',
                    'notification_email' => '',
                    'last_scan'          => '',
                ),
            );
        }

        $username = whp_ai_monitor_getWhpUsername($params);
        $siteId   = $params['customfields']['Monitored Site'] ?? '';

        // Fetch monitoring status from the WHP API
        $queryString = http_build_query(array(
            'action'   => 'status',
            'username' => $username,
            'site_id'  => $siteId,
        ));

        $response = whp_ai_monitor_api_call($serverData, 'ai-monitor.php?' . $queryString, 'GET');

        $data = $response['data'] ?? array();

        // Build SSO dashboard URL if not provided by the API
        $dashboardUrl = $data['dashboard_url'] ?? '';
        if (empty($dashboardUrl)) {
            $protocol = $serverData['secure'] ? 'https' : 'http';
            $port     = $serverData['port'] ?: ($serverData['secure'] ? '443' : '80');
            $dashboardUrl = $protocol . '://' . $serverData['hostname'] . ':' . $port . '/?page=ai-monitor';
        }

        return array(
            'templatefile' => 'templates/clientarea',
            'vars'         => array(
                'monitoring_status'  => $data['status'] ?? 'inactive',
                'site_name'          => $data['site_name'] ?? $siteId,
                'issue_count'        => intval($data['issue_count'] ?? 0),
                'critical_count'     => intval($data['critical_count'] ?? 0),
                'warning_count'      => intval($data['warning_count'] ?? 0),
                'info_count'         => intval($data['info_count'] ?? 0),
                'dashboard_url'      => $dashboardUrl,
                'notification_email' => $data['notification_email'] ?? '',
                'last_scan'          => $data['last_scan'] ?? 'Never',
                'error'              => '',
            ),
        );

    } catch (Exception $e) {
        logModuleCall('whp_ai_monitor', __FUNCTION__, $params, $e->getMessage());

        return array(
            'templatefile' => 'templates/clientarea',
            'vars'         => array(
                'error'              => 'Unable to retrieve monitoring status: ' . $e->getMessage(),
                'monitoring_status'  => 'unknown',
                'site_name'          => $params['customfields']['Monitored Site'] ?? '',
                'issue_count'        => 0,
                'critical_count'     => 0,
                'warning_count'      => 0,
                'info_count'         => 0,
                'dashboard_url'      => '',
                'notification_email' => '',
                'last_scan'          => '',
            ),
        );
    }
}
