<?php
/**
 * Teleship Connection Handler
 *
 * Handles the connection flow between WooCommerce and Teleship.
 * Includes Connect/Disconnect functionality and admin UI.
 *
 * @package Teleship
 * @since 2.0.0
 */

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

/**
 * Class Teleship_Connection
 *
 * Manages the connection between WooCommerce and Teleship
 */
class Teleship_Connection {

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

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

    /**
     * Constructor
     */
    private function __construct() {
        // Add admin hooks
        add_action('admin_init', array($this, 'handle_connection_actions'));
        add_action('admin_notices', array($this, 'display_connection_notices'));

        // Add AJAX handlers
        add_action('wp_ajax_teleship_connect', array($this, 'ajax_connect'));
        // Disconnect is handled by plugin deactivation hook, no AJAX handler needed
        add_action('wp_ajax_teleship_test_connection', array($this, 'ajax_test_connection'));
        add_action('wp_ajax_teleship_sync_orders', array($this, 'ajax_sync_orders'));
        add_action('wp_ajax_teleship_sync_products', array($this, 'ajax_sync_products'));

        // Register REST endpoint for OAuth callback
        add_action('rest_api_init', array($this, 'register_callback_endpoint'));
    }

    /**
     * Initialize connection handler
     */
    public static function init() {
        self::instance();
    }

    /**
     * Register OAuth callback endpoint
     */
    public function register_callback_endpoint() {
        register_rest_route('teleship/v1', '/oauth/callback', array(
            'methods'             => 'GET',
            'callback'            => array($this, 'handle_oauth_callback'),
            'permission_callback' => '__return_true',
        ));

        register_rest_route('teleship/v1', '/oauth/callback', array(
            'methods'             => 'POST',
            'callback'            => array($this, 'handle_oauth_callback'),
            'permission_callback' => '__return_true',
        ));
    }

    /**
     * Handle OAuth callback from Teleship
     *
     * Accepts the same params as Magento's OAuth callback:
     * account_client_id, account_client_secret, account_id, code, state
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response|WP_Error
     */
    public function handle_oauth_callback($request) {
        teleship_log('[Connection] OAuth callback received');

        // Accept Magento-style OAuth callback params
        $account_client_id = $request->get_param('account_client_id');
        $account_client_secret = $request->get_param('account_client_secret');
        $account_id = $request->get_param('account_id');
        $state = $request->get_param('state');

        // Validate CSRF state
        $stored_state = get_transient('teleship_oauth_state');
        if (empty($state) || $state !== $stored_state) {
            teleship_log('[Connection] OAuth callback state mismatch');
            return new WP_Error('invalid_state', 'Invalid or expired OAuth state', array('status' => 403));
        }
        delete_transient('teleship_oauth_state');

        // Validate required fields
        if (empty($account_client_id) || empty($account_client_secret) || empty($account_id)) {
            teleship_log('[Connection] OAuth callback missing required fields');
            return new WP_Error('missing_fields', 'Missing required connection data', array('status' => 400));
        }

        // Save connection using existing save_connection()
        $oauth = teleship_oauth();
        $result = $oauth->save_connection(array(
            'clientId'    => $account_client_id,
            'clientSecret' => $account_client_secret,
            'accountId'   => $account_id,
        ));

        if (!$result) {
            return new WP_Error('save_failed', 'Failed to save connection', array('status' => 500));
        }

        // Exchange credentials for initial bearer token
        $token = $oauth->get_bearer_token();

        if (empty($token)) {
            teleship_log('[Connection] Failed to get bearer token after OAuth callback');
        } else {
            // Send WC REST API credentials to Teleship
            $this->send_credentials_to_teleship($token, $account_id);

            // Register webhook automatically
            $webhook_result = teleship_webhook_manager()->register();
            teleship_log('[Connection] Webhook registration result: ' . wp_json_encode($webhook_result));
        }

        // Clear session validation cache so connected state is detected immediately
        delete_transient('teleship_session_valid');

        // Schedule initial product + order sync as background jobs (non-blocking)
        $scheduler = teleship_sync_scheduler();
        $scheduler->schedule_initial_sync();
        teleship_log('[Connection] Initial sync scheduled (async via Action Scheduler)');

        // Redirect browser to the Teleship app page (orders) after successful connection
        $redirect_url = admin_url('admin.php?page=teleship-app');

        // Use wp_redirect for browser redirects (OAuth callback is a GET request)
        if (!headers_sent()) {
            wp_safe_redirect($redirect_url);
            exit;
        }

        // Fallback: return JSON with redirect URL
        return new WP_REST_Response(array(
            'success'     => true,
            'message'     => 'Connected successfully',
            'redirectUrl' => $redirect_url,
        ), 200);
    }

    /**
     * Handle connection actions from admin
     */
    public function handle_connection_actions() {
        // Reserved for future admin-initiated connection actions
    }

    /**
     * Display connection notices
     */
    public function display_connection_notices() {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking page parameter for display
        $page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
        if ('teleship-settings' !== $page) {
            return;
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display-only, no state change
        if (isset($_GET['connected'])) {
            echo '<div class="notice notice-success is-dismissible"><p>';
            esc_html_e('Successfully connected to Teleship!', 'teleship-global-shipping');
            echo '</p></div>';
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display-only, no state change
        if (isset($_GET['disconnected'])) {
            echo '<div class="notice notice-info is-dismissible"><p>';
            esc_html_e('Disconnected from Teleship.', 'teleship-global-shipping');
            echo '</p></div>';
        }

        // Check connection status and show warnings
        $oauth = teleship_oauth();
        if ($oauth->is_connected()) {
            $validation = $oauth->validate_connection();
            if ($validation) {
                echo '<div class="notice notice-warning"><p>';
                echo esc_html($validation);
                echo '</p></div>';
            }
        }
    }

    /**
     * Get the Teleship connect URL (OAuth authorize flow)
     *
     * Redirects to the same /oauth/authorize endpoint used by Magento.
     *
     * @return string
     */
    public function get_connect_url() {
        // Generate CSRF state token
        $state = wp_generate_password(32, false);
        set_transient('teleship_oauth_state', $state, 600); // 10 min expiry

        $params = array(
            'clientId'     => TELESHIP_OAUTH_CLIENT_ID,
            'redirectUri'  => rest_url('teleship/v1/oauth/callback'),
            'responseType' => 'code',
            'state'        => $state,
            'scope'        => 'read_accounts write_accounts read_shipments write_shipments',
        );

        $connect_url = teleship_get_api_url() . '/oauth/authorize?' . http_build_query($params);

        return $connect_url;
    }

    /**
     * Send WC REST API credentials to Teleship
     *
     * Generates WC REST API keys and sends them along with store info
     * to POST /api/platforms/{clientId}/credentials (same endpoint as Magento).
     *
     * @param string $token Bearer token.
     * @param string $account_id Account ID.
     */
    private function send_credentials_to_teleship($token, $account_id) {
        $store_url = get_site_url();
        $store_name = get_bloginfo('name');

        // Generate WC REST API keys for Teleship
        $api_keys = $this->generate_wc_api_keys();

        if (!$api_keys) {
            teleship_log('[Connection] Failed to generate WC REST API keys');
            return;
        }

        $api_url = teleship_get_api_url() . '/api/platforms/' . TELESHIP_OAUTH_CLIENT_ID . '/credentials';

        teleship_log('[Connection] Sending credentials to Teleship: ' . $api_url);

        $response = wp_remote_post($api_url, array(
            'timeout' => 30,
            'headers' => array(
                'Authorization' => 'Bearer ' . $token,
                'Content-Type'  => 'application/json',
                'x-account-id'  => $account_id,
            ),
            'body' => wp_json_encode(array(
                'accountId'      => $account_id,
                'store_url'      => $store_url,
                'store_name'     => $store_name,
                'consumer_key'   => $api_keys['consumer_key'],
                'consumer_secret' => $api_keys['consumer_secret'],
                'version'        => TELESHIP_VERSION,
            )),
        ));

        if (is_wp_error($response)) {
            teleship_log('[Connection] Failed to send credentials: ' . $response->get_error_message());
            return;
        }

        $http_code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);
        teleship_log('[Connection] Credentials sent, HTTP ' . $http_code);

        if (isset($body['integrationId'])) {
            update_option('teleship_integration_id', $body['integrationId']);
            teleship_log('[Connection] Integration ID saved: ' . $body['integrationId']);
        }
    }

    /**
     * Generate WC REST API keys for Teleship
     *
     * Creates a set of read/write API keys that Teleship can use to
     * call back into the WC store (e.g., to update product HS codes).
     *
     * @return array|false Array with consumer_key and consumer_secret, or false on failure.
     */
    private function generate_wc_api_keys() {
        global $wpdb;

        if (!function_exists('wc_rand_hash') || !function_exists('wc_api_hash')) {
            teleship_log('[Connection] WooCommerce functions not available');
            return false;
        }

        // Check if we already have keys
        $existing_key_id = get_option('teleship_wc_api_key_id');
        if ($existing_key_id) {
            // Delete old key before creating a new one
            $wpdb->delete($wpdb->prefix . 'woocommerce_api_keys', array('key_id' => $existing_key_id), array('%d')); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- WC has no PHP API for key management
            delete_option('teleship_wc_api_key_id');
        }

        $consumer_key = 'ck_' . wc_rand_hash();
        $consumer_secret = 'cs_' . wc_rand_hash();

        $result = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- WC has no PHP API for key management
            $wpdb->prefix . 'woocommerce_api_keys',
            array(
                'user_id'         => get_current_user_id(),
                'description'     => 'Teleship Global Shipping',
                'permissions'     => 'read_write',
                'consumer_key'    => wc_api_hash($consumer_key),
                'consumer_secret' => $consumer_secret,
                'truncated_key'   => substr($consumer_key, -7),
            ),
            array('%d', '%s', '%s', '%s', '%s', '%s')
        );

        if (!$result) {
            teleship_log('[Connection] Failed to insert WC API key');
            return false;
        }

        // Save key ID for later cleanup on disconnect
        update_option('teleship_wc_api_key_id', $wpdb->insert_id);

        teleship_log('[Connection] WC REST API keys generated successfully');

        return array(
            'consumer_key'    => $consumer_key,
            'consumer_secret' => $consumer_secret,
        );
    }

    /**
     * Delete WC REST API keys created for Teleship
     */
    private function delete_wc_api_keys() {
        global $wpdb;

        $key_id = get_option('teleship_wc_api_key_id');
        if ($key_id) {
            $wpdb->delete($wpdb->prefix . 'woocommerce_api_keys', array('key_id' => $key_id), array('%d')); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- WC has no PHP API for key management
            delete_option('teleship_wc_api_key_id');
            teleship_log('[Connection] WC REST API keys deleted');
        }
    }

    /**
     * Disconnect from Teleship
     *
     * @return array Result array
     */
    public function disconnect() {
        teleship_log('[Connection] Disconnecting from Teleship');

        // Unregister webhook
        $webhook_manager = teleship_webhook_manager();
        if ($webhook_manager->is_registered()) {
            $webhook_manager->unregister();
        }

        // Delete WC REST API keys created for Teleship
        $this->delete_wc_api_keys();

        // Clear OAuth data
        teleship_oauth()->disconnect();

        // Clear integration ID
        delete_option('teleship_integration_id');

        // Clear session validation cache so disconnected state is detected immediately
        delete_transient('teleship_session_valid');

        teleship_log('[Connection] Disconnected successfully');

        return array(
            'success' => true,
            'message' => 'Disconnected successfully',
        );
    }

    /**
     * AJAX handler for connect
     */
    public function ajax_connect() {
        check_ajax_referer('teleship_admin_nonce', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $connect_url = $this->get_connect_url();

        wp_send_json_success(array(
            'connect_url' => $connect_url,
        ));
    }

    /**
     * AJAX handler for disconnect
     */
    public function ajax_disconnect() {
        check_ajax_referer('teleship_admin_nonce', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $result = $this->disconnect();

        if ($result['success']) {
            wp_send_json_success($result);
        } else {
            wp_send_json_error($result);
        }
    }

    /**
     * AJAX handler for test connection
     */
    public function ajax_test_connection() {
        check_ajax_referer('teleship_admin_nonce', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $oauth = teleship_oauth();

        if (!$oauth->is_connected()) {
            wp_send_json_error(array('message' => 'Not connected to Teleship'));
        }

        // Try to get a bearer token (this validates the credentials)
        $token = $oauth->get_bearer_token();

        if (empty($token)) {
            wp_send_json_error(array('message' => 'Failed to authenticate with Teleship'));
        }

        // Try to fetch account info
        $api_url = teleship_get_api_url() . '/api/accounts/me';

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

        if (is_wp_error($response)) {
            wp_send_json_error(array('message' => 'Connection test failed: ' . $response->get_error_message()));
        }

        $http_code = wp_remote_retrieve_response_code($response);

        if ($http_code !== 200) {
            wp_send_json_error(array('message' => 'Connection test failed: HTTP ' . $http_code));
        }

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

        wp_send_json_success(array(
            'message'    => 'Connection successful!',
            'account_id' => $body['id'] ?? $oauth->get_account_id(),
            'name'       => $body['name'] ?? '',
        ));
    }

    /**
     * AJAX handler for sync orders — schedules async job
     */
    public function ajax_sync_orders() {
        check_ajax_referer('teleship_admin_nonce', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $scheduler = teleship_sync_scheduler();
        $scheduler->schedule_order_sync();

        wp_send_json_success(array(
            'scheduled' => true,
            'message'   => __('Order sync scheduled. It will run in the background.', 'teleship-global-shipping'),
        ));
    }

    /**
     * AJAX handler for sync products — schedules async job
     */
    public function ajax_sync_products() {
        check_ajax_referer('teleship_admin_nonce', 'nonce');

        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => 'Permission denied'));
        }

        $scheduler = teleship_sync_scheduler();
        $scheduler->schedule_product_sync();

        wp_send_json_success(array(
            'scheduled' => true,
            'message'   => __('Product sync scheduled. It will run in the background.', 'teleship-global-shipping'),
        ));
    }

    /**
     * Render connection status UI
     */
    public function render_connection_status() {
        $oauth = teleship_oauth();
        $status = $oauth->get_connection_status();
        ?>
        <div class="teleship-connection-status">
            <?php if ($status['is_connected']) : ?>
                <div class="teleship-connected">
                    <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
                    <strong><?php esc_html_e('Connected to Teleship', 'teleship-global-shipping'); ?></strong>
                </div>

                <table class="form-table">
                    <tr>
                        <th><?php esc_html_e('Account ID', 'teleship-global-shipping'); ?></th>
                        <td><code><?php echo esc_html($status['account_id']); ?></code></td>
                    </tr>
                    <tr>
                        <th><?php esc_html_e('Connected At', 'teleship-global-shipping'); ?></th>
                        <td><?php echo esc_html($status['connected_at']); ?></td>
                    </tr>
                    <?php if ($status['expires_at']) : ?>
                    <tr>
                        <th><?php esc_html_e('Token Expires', 'teleship-global-shipping'); ?></th>
                        <td>
                            <?php echo esc_html($status['expires_at']); ?>
                            <?php if ($status['can_auto_refresh']) : ?>
                                <span class="description">(<?php esc_html_e('auto-refresh enabled', 'teleship-global-shipping'); ?>)</span>
                            <?php endif; ?>
                        </td>
                    </tr>
                    <?php endif; ?>
                    <tr>
                        <th><?php esc_html_e('Webhook', 'teleship-global-shipping'); ?></th>
                        <td>
                            <?php if (teleship_webhook_manager()->is_registered()) : ?>
                                <span class="dashicons dashicons-yes" style="color: #46b450;"></span>
                                <?php esc_html_e('Registered', 'teleship-global-shipping'); ?>
                            <?php else : ?>
                                <span class="dashicons dashicons-no" style="color: #dc3232;"></span>
                                <?php esc_html_e('Not registered', 'teleship-global-shipping'); ?>
                            <?php endif; ?>
                        </td>
                    </tr>
                </table>

                <p class="submit">
                    <button type="button" class="button" id="teleship-test-connection">
                        <?php esc_html_e('Test Connection', 'teleship-global-shipping'); ?>
                    </button>
                </p>

            <?php else : ?>
                <div class="teleship-disconnected">
                    <span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
                    <strong><?php esc_html_e('Not connected to Teleship', 'teleship-global-shipping'); ?></strong>
                </div>

                <p><?php esc_html_e('Connect your WooCommerce store to Teleship to enable global shipping, product classification, and real-time rates.', 'teleship-global-shipping'); ?></p>

                <p class="submit">
                    <a href="<?php echo esc_url($this->get_connect_url()); ?>" class="button button-primary button-hero">
                        <?php esc_html_e('Connect to Teleship', 'teleship-global-shipping'); ?>
                    </a>
                </p>
            <?php endif; ?>
        </div>

        <script type="text/javascript">
        jQuery(document).ready(function($) {
            $('#teleship-test-connection').on('click', function() {
                var $btn = $(this);
                $btn.prop('disabled', true).text('<?php esc_attr_e('Testing...', 'teleship-global-shipping'); ?>');

                $.post(ajaxurl, {
                    action: 'teleship_test_connection',
                    nonce: '<?php echo esc_js(wp_create_nonce('teleship_admin_nonce')); ?>'
                }, function(response) {
                    if (response.success) {
                        alert('<?php esc_attr_e('Connection successful!', 'teleship-global-shipping'); ?>' + '\n\n' + response.data.message);
                    } else {
                        alert('<?php esc_attr_e('Connection failed:', 'teleship-global-shipping'); ?>' + ' ' + response.data.message);
                    }
                }).always(function() {
                    $btn.prop('disabled', false).text('<?php esc_attr_e('Test Connection', 'teleship-global-shipping'); ?>');
                });
            });
        });
        </script>
        <?php
    }

    /**
     * Render sync actions UI
     */
    public function render_sync_actions() {
        if (!teleship_oauth()->is_connected()) {
            return;
        }
        ?>
        <div class="teleship-sync-actions">
            <h3><?php esc_html_e('Data Synchronization', 'teleship-global-shipping'); ?></h3>

            <table class="form-table">
                <tr>
                    <th><?php esc_html_e('Sync Products', 'teleship-global-shipping'); ?></th>
                    <td>
                        <button type="button" class="button" id="teleship-sync-products">
                            <?php esc_html_e('Sync All Products', 'teleship-global-shipping'); ?>
                        </button>
                        <p class="description">
                            <?php esc_html_e('Push all products to Teleship for HS code classification.', 'teleship-global-shipping'); ?>
                        </p>
                    </td>
                </tr>
                <tr>
                    <th><?php esc_html_e('Sync Orders', 'teleship-global-shipping'); ?></th>
                    <td>
                        <button type="button" class="button" id="teleship-sync-orders">
                            <?php esc_html_e('Sync Processing Orders', 'teleship-global-shipping'); ?>
                        </button>
                        <p class="description">
                            <?php esc_html_e('Push all orders with "Processing" status to Teleship.', 'teleship-global-shipping'); ?>
                        </p>
                    </td>
                </tr>
            </table>

            <div id="teleship-sync-status" style="display: none; margin-top: 20px; padding: 15px; background: #f0f0f1;"></div>
        </div>

        <script type="text/javascript">
        jQuery(document).ready(function($) {
            var pollTimer = null;

            function pollSyncStatus() {
                $.post(ajaxurl, {
                    action: 'teleship_sync_status',
                    nonce: '<?php echo esc_js(wp_create_nonce('teleship_admin_nonce')); ?>'
                }, function(response) {
                    if (!response.success) return;
                    var d = response.data;
                    var parts = [];
                    if (d.products && d.products.status !== 'idle') {
                        parts.push('Products: ' + d.products.status);
                    }
                    if (d.orders && d.orders.status !== 'idle') {
                        parts.push('Orders: ' + d.orders.status);
                    }
                    if (parts.length) {
                        $('#teleship-sync-status').show().html(parts.join(' &mdash; '));
                    }
                    var done = (!d.products || d.products.status === 'idle' || d.products.status === 'completed' || d.products.status === 'failed')
                            && (!d.orders || d.orders.status === 'idle' || d.orders.status === 'completed' || d.orders.status === 'failed');
                    if (done && pollTimer) {
                        clearInterval(pollTimer);
                        pollTimer = null;
                        $('#teleship-sync-products, #teleship-sync-orders').prop('disabled', false);
                    }
                });
            }

            function runSync(action) {
                var $status = $('#teleship-sync-status');
                var $btn = $(this);
                $btn.prop('disabled', true);
                $status.show().html('<?php esc_attr_e('Scheduling sync...', 'teleship-global-shipping'); ?>');

                $.post(ajaxurl, {
                    action: action,
                    nonce: '<?php echo esc_js(wp_create_nonce('teleship_admin_nonce')); ?>'
                }, function(response) {
                    if (response.success && response.data.scheduled) {
                        $status.html(response.data.message);
                        if (!pollTimer) {
                            pollTimer = setInterval(pollSyncStatus, 3000);
                        }
                    } else {
                        $status.html('<span style="color: #dc3232;">✗</span> ' + (response.data ? response.data.message : '<?php esc_attr_e('Sync failed.', 'teleship-global-shipping'); ?>'));
                        $btn.prop('disabled', false);
                    }
                }).fail(function() {
                    $status.html('<span style="color: #dc3232;">✗</span> <?php esc_attr_e('Sync request failed. Please try again.', 'teleship-global-shipping'); ?>');
                    $btn.prop('disabled', false);
                });
            }

            $('#teleship-sync-products').on('click', function() {
                runSync.call(this, 'teleship_sync_products');
            });

            $('#teleship-sync-orders').on('click', function() {
                runSync.call(this, 'teleship_sync_orders');
            });
        });
        </script>
        <?php
    }
}

/**
 * Get Teleship Connection instance
 *
 * @return Teleship_Connection
 */
function teleship_connection() {
    return Teleship_Connection::instance();
}

// Initialize on plugins_loaded
add_action('plugins_loaded', array('Teleship_Connection', 'init'), 15);
