<?php
/**
 * Teleship Webhook Manager
 *
 * Handles automatic registration and management of webhooks with Teleship API.
 * Mirrors functionality from Magento's WebhookManager.php
 *
 * @package Teleship
 * @since 2.0.0
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Class Teleship_Webhook_Manager
 *
 * Manages webhook registration with Teleship
 */
class Teleship_Webhook_Manager {

    /**
     * Webhook events to subscribe to
     */
    const WEBHOOK_EVENTS = array(
        'label.generated',
        'shipment.updated',
        'manifest.created',
        'product.classification.complete',
        'product.updated',
    );

    /**
     * Singleton instance
     *
     * @var Teleship_Webhook_Manager
     */
    private static $instance = null;

    /**
     * Get singleton instance
     *
     * @return Teleship_Webhook_Manager
     */
    public static function instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor
     */
    private function __construct() {
        // Private constructor for singleton
    }

    /**
     * Register webhook with Teleship
     *
     * Checks for existing webhooks first to prevent duplicates:
     * - If webhook exists and is enabled, reuses it and saves its secret
     * - If webhook exists but is disabled, updates it to enabled
     * - If no webhook exists, creates a new one
     *
     * IMPORTANT: The secret from Teleship's response is saved to WordPress options.
     * WordPress does NOT generate its own secret - it must use Teleship's secret
     * to properly verify incoming webhook signatures.
     *
     * @return array Result with 'success' and 'message' keys
     */
    public function register() {
        try {
            // Get webhook URL
            $webhook_url = $this->get_webhook_url();

            teleship_log('[Webhook Manager] Checking for existing webhooks at: ' . $webhook_url);

            // Check for existing webhook with this URL
            $existing_webhook = $this->find_existing_webhook($webhook_url);

            if ($existing_webhook) {
                return $this->handle_existing_webhook($existing_webhook, $webhook_url);
            }

            // No existing webhook found - create a new one
            return $this->create_new_webhook($webhook_url);

        } catch (Exception $e) {
            teleship_log('[Webhook Manager] Failed to register webhook: ' . $e->getMessage());

            return array(
                'success' => false,
                'message' => 'Failed to register webhook: ' . $e->getMessage(),
            );
        }
    }

    /**
     * Find existing webhook by URL
     *
     * @param string $webhook_url The webhook URL to search for.
     * @return array|null The webhook data if found, null otherwise
     */
    private function find_existing_webhook($webhook_url) {
        try {
            $oauth = teleship_oauth();
            $auth_header = $oauth->get_authorization_header();

            if (empty($auth_header)) {
                teleship_log('[Webhook Manager] No auth token available to list webhooks');
                return null;
            }

            $api_url = teleship_get_api_url() . '/api/webhooks';

            $response = wp_remote_get($api_url, array(
                'timeout' => 30,
                'headers' => array(
                    'Authorization' => $auth_header,
                    'Content-Type'  => 'application/json',
                ),
            ));

            if (is_wp_error($response)) {
                teleship_log('[Webhook Manager] Failed to list webhooks: ' . $response->get_error_message());
                return null;
            }

            $http_code = wp_remote_retrieve_response_code($response);
            if ($http_code !== 200) {
                teleship_log('[Webhook Manager] List webhooks returned HTTP ' . $http_code);
                return null;
            }

            $body = json_decode(wp_remote_retrieve_body($response), true);

            if (!is_array($body)) {
                return null;
            }

            // Search for webhook matching our URL
            foreach ($body as $webhook) {
                if (isset($webhook['url']) && $webhook['url'] === $webhook_url) {
                    teleship_log('[Webhook Manager] Found existing webhook: ' . ($webhook['id'] ?? 'unknown'));
                    return $webhook;
                }
            }

            return null;

        } catch (Exception $e) {
            teleship_log('[Webhook Manager] Could not check for existing webhooks: ' . $e->getMessage());
            return null;
        }
    }

    /**
     * Handle existing webhook - update if disabled, reuse if enabled
     *
     * @param array  $existing_webhook The existing webhook data.
     * @param string $webhook_url      The webhook URL.
     * @return array Result array
     */
    private function handle_existing_webhook($existing_webhook, $webhook_url) {
        $webhook_id = $existing_webhook['id'];
        $is_enabled = isset($existing_webhook['enabled']) ? $existing_webhook['enabled'] : false;
        $secret = isset($existing_webhook['secret']) ? $existing_webhook['secret'] : null;

        if (!$is_enabled) {
            // Webhook exists but is disabled - update it to enabled
            teleship_log('[Webhook Manager] Enabling existing disabled webhook: ' . $webhook_id);

            try {
                $oauth = teleship_oauth();
                $auth_header = $oauth->get_authorization_header();

                $api_url = teleship_get_api_url() . '/api/webhooks/' . $webhook_id;

                $response = wp_remote_request($api_url, array(
                    'method'  => 'PUT',
                    'timeout' => 30,
                    'headers' => array(
                        'Authorization' => $auth_header,
                        'Content-Type'  => 'application/json',
                    ),
                    'body'    => wp_json_encode(array(
                        'enabled'       => true,
                        'enabledEvents' => self::WEBHOOK_EVENTS,
                    )),
                ));

                if (!is_wp_error($response)) {
                    $body = json_decode(wp_remote_retrieve_body($response), true);
                    if (isset($body['secret'])) {
                        $secret = $body['secret'];
                    }
                }

            } catch (Exception $e) {
                teleship_log('[Webhook Manager] Failed to enable existing webhook: ' . $e->getMessage());
            }
        }

        // Save Teleship's secret to WordPress options
        if (!empty($secret)) {
            teleship_oauth()->save_webhook_data($webhook_id, $secret);
            teleship_log('[Webhook Manager] Saved webhook secret from existing webhook');
        } else {
            teleship_log('[Webhook Manager] Warning: Existing webhook has no secret');
        }

        return array(
            'success'    => true,
            'message'    => $is_enabled ? 'Using existing webhook' : 'Existing webhook enabled',
            'webhook_id' => $webhook_id,
        );
    }

    /**
     * Create a new webhook
     *
     * @param string $webhook_url The webhook URL.
     * @return array Result array
     */
    private function create_new_webhook($webhook_url) {
        teleship_log('[Webhook Manager] Creating new webhook at: ' . $webhook_url);

        $oauth = teleship_oauth();
        $auth_header = $oauth->get_authorization_header();

        if (empty($auth_header)) {
            return array(
                'success' => false,
                'message' => 'No authentication token available',
            );
        }

        $api_url = teleship_get_api_url() . '/api/webhooks';

        $webhook_data = array(
            'url'           => $webhook_url,
            'enabledEvents' => self::WEBHOOK_EVENTS,
            'enabled'       => true,
            'description'   => 'WooCommerce integration webhook',
            'metadata'      => array(
                'source'    => 'woocommerce',
                'store_url' => get_site_url(),
                'plugin_version' => defined('TELESHIP_VERSION') ? TELESHIP_VERSION : '2.0.0',
            ),
        );

        $response = wp_remote_post($api_url, array(
            'timeout' => 30,
            'headers' => array(
                'Authorization' => $auth_header,
                'Content-Type'  => 'application/json',
            ),
            'body'    => wp_json_encode($webhook_data),
        ));

        if (is_wp_error($response)) {
            return array(
                'success' => false,
                'message' => 'Failed to create webhook: ' . $response->get_error_message(),
            );
        }

        $http_code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);

        if ($http_code !== 200 && $http_code !== 201) {
            return array(
                'success' => false,
                'message' => 'Failed to create webhook: HTTP ' . $http_code,
            );
        }

        if (!isset($body['id'])) {
            return array(
                'success' => false,
                'message' => 'Invalid response from Teleship API - missing webhook ID',
            );
        }

        $webhook_id = $body['id'];

        // CRITICAL: Save Teleship's generated secret to WordPress options
        // Teleship generates the secret and signs webhooks with it.
        // WordPress must use THIS secret to verify incoming webhook signatures.
        if (isset($body['secret'])) {
            teleship_oauth()->save_webhook_data($webhook_id, $body['secret']);
            teleship_log('[Webhook Manager] Saved Teleship webhook secret to options');
        } else {
            teleship_log('[Webhook Manager] WARNING: No secret in response - signature verification will fail!');
        }

        teleship_log('[Webhook Manager] Webhook registered successfully: ' . $webhook_id);

        return array(
            'success'    => true,
            'message'    => 'Webhook registered successfully',
            'webhook_id' => $webhook_id,
        );
    }

    /**
     * Get webhook URL for this WordPress store
     *
     * @return string
     */
    public function get_webhook_url() {
        // Return the REST API webhook endpoint
        return rest_url('teleship/v1/webhook');
    }

    /**
     * Unregister webhook from Teleship
     *
     * @param string $webhook_id Optional webhook ID. If not provided, uses stored ID.
     * @return array Result with 'success' and 'message' keys
     */
    public function unregister($webhook_id = null) {
        if (empty($webhook_id)) {
            $webhook_id = teleship_oauth()->get_webhook_id();
        }

        if (empty($webhook_id)) {
            return array(
                'success' => false,
                'message' => 'No webhook ID to unregister',
            );
        }

        try {
            teleship_log('[Webhook Manager] Unregistering webhook: ' . $webhook_id);

            $oauth = teleship_oauth();
            $auth_header = $oauth->get_authorization_header();

            if (empty($auth_header)) {
                return array(
                    'success' => false,
                    'message' => 'No authentication token available',
                );
            }

            $api_url = teleship_get_api_url() . '/api/webhooks/' . $webhook_id;

            $response = wp_remote_request($api_url, array(
                'method'  => 'DELETE',
                'timeout' => 30,
                'headers' => array(
                    'Authorization' => $auth_header,
                    'Content-Type'  => 'application/json',
                ),
            ));

            if (is_wp_error($response)) {
                return array(
                    'success' => false,
                    'message' => 'Failed to unregister webhook: ' . $response->get_error_message(),
                );
            }

            teleship_log('[Webhook Manager] Webhook unregistered successfully');

            return array(
                'success' => true,
                'message' => 'Webhook unregistered successfully',
            );

        } catch (Exception $e) {
            teleship_log('[Webhook Manager] Failed to unregister webhook: ' . $e->getMessage());

            return array(
                'success' => false,
                'message' => 'Failed to unregister webhook: ' . $e->getMessage(),
            );
        }
    }

    /**
     * Check if webhook is registered
     *
     * @return bool
     */
    public function is_registered() {
        return !empty(teleship_oauth()->get_webhook_id());
    }

    /**
     * Get the list of webhook events
     *
     * @return array
     */
    public function get_webhook_events() {
        return self::WEBHOOK_EVENTS;
    }
}

/**
 * Get Teleship Webhook Manager instance
 *
 * @return Teleship_Webhook_Manager
 */
function teleship_webhook_manager() {
    return Teleship_Webhook_Manager::instance();
}
