<?php
/**
 * Cast Conductor Proprietary License v5
 * SPDX-License-Identifier: LicenseRef-CastConductor-Proprietary-v5
 * 
 * Copyright (c) 2025 CastConductor.com. All Rights Reserved.
 * See LICENSE and EULA-v5.2.md for full terms.
 */

/**
 * CastConductor Analytics Integrations
 * 
 * Handles external integrations for analytics data including:
 * - Custom webhooks
 * - Google Analytics 4 (Measurement Protocol)
 * - Segment
 * 
 * These features are tier-gated (Business+).
 * 
 * @package CastConductor
 * @subpackage Analytics
 * @since 5.8.0
 */

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

class CC_Analytics_Integrations {

    /**
     * Option keys
     */
    const OPTION_WEBHOOKS = 'cc_analytics_webhooks';
    const OPTION_GA4      = 'cc_analytics_ga4';
    const OPTION_SEGMENT  = 'cc_analytics_segment';

    /**
     * Single instance
     */
    private static $instance = null;

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

    /**
     * Constructor
     */
    private function __construct() {
        // Listen for stored events
        add_action('cc_analytics_event_stored', [$this, 'dispatch_event'], 10, 2);
    }

    /**
     * Dispatch event to configured integrations
     * 
     * @param array $event Event data
     * @param int $event_id Event ID
     */
    public function dispatch_event($event, $event_id) {
        // Only dispatch if user has integration features
        if (!CC_Analytics_Helpers::has_feature('webhooks')) {
            return;
        }
        
        // Dispatch to webhooks
        $this->dispatch_to_webhooks($event);
        
        // Dispatch to GA4 if configured
        if (CC_Analytics_Helpers::has_feature('segment')) {
            $this->dispatch_to_ga4($event);
            $this->dispatch_to_segment($event);
        }
    }

    // =========================================================================
    // Webhook Integration
    // =========================================================================

    /**
     * Get configured webhooks
     * 
     * @return array Webhook configurations
     */
    public function get_webhooks() {
        return get_option(self::OPTION_WEBHOOKS, []);
    }

    /**
     * Save webhook configuration
     * 
     * @param array $webhooks Webhook configurations
     */
    public function save_webhooks($webhooks) {
        update_option(self::OPTION_WEBHOOKS, $webhooks);
    }

    /**
     * Add a webhook
     * 
     * @param array $webhook Webhook config (url, events, secret, enabled)
     * @return string Webhook ID
     */
    public function add_webhook($webhook) {
        $webhooks = $this->get_webhooks();
        
        $id = 'wh_' . bin2hex(random_bytes(8));
        
        $webhooks[$id] = [
            'id'      => $id,
            'url'     => esc_url_raw($webhook['url']),
            'events'  => $webhook['events'] ?? ['*'], // ['*'] = all events
            'secret'  => $webhook['secret'] ?? wp_generate_password(32, false),
            'enabled' => $webhook['enabled'] ?? true,
            'created' => CC_Analytics_Helpers::now_utc(),
        ];
        
        $this->save_webhooks($webhooks);
        
        return $id;
    }

    /**
     * Remove a webhook
     * 
     * @param string $id Webhook ID
     */
    public function remove_webhook($id) {
        $webhooks = $this->get_webhooks();
        unset($webhooks[$id]);
        $this->save_webhooks($webhooks);
    }

    /**
     * Dispatch event to all configured webhooks
     * 
     * @param array $event Event data
     */
    private function dispatch_to_webhooks($event) {
        $webhooks = $this->get_webhooks();
        
        foreach ($webhooks as $webhook) {
            if (!$webhook['enabled']) {
                continue;
            }
            
            // Check if webhook wants this event type
            if (!$this->webhook_wants_event($webhook, $event['event_type'])) {
                continue;
            }
            
            // Send async (non-blocking)
            $this->send_webhook($webhook, $event);
        }
    }

    /**
     * Check if webhook is subscribed to event type
     * 
     * @param array $webhook Webhook config
     * @param string $event_type Event type
     * @return bool
     */
    private function webhook_wants_event($webhook, $event_type) {
        $events = $webhook['events'] ?? ['*'];
        
        // All events
        if (in_array('*', $events, true)) {
            return true;
        }
        
        // Specific event
        if (in_array($event_type, $events, true)) {
            return true;
        }
        
        // Event category (e.g., 'session_*')
        foreach ($events as $pattern) {
            if (str_ends_with($pattern, '*')) {
                $prefix = rtrim($pattern, '*');
                if (str_starts_with($event_type, $prefix)) {
                    return true;
                }
            }
        }
        
        return false;
    }

    /**
     * Send webhook request (non-blocking)
     * 
     * @param array $webhook Webhook config
     * @param array $event Event data
     */
    private function send_webhook($webhook, $event) {
        $payload = [
            'event'     => $event,
            'timestamp' => CC_Analytics_Helpers::now_utc(),
            'site_url'  => home_url(),
        ];
        
        $body = wp_json_encode($payload);
        
        // Generate signature
        $signature = hash_hmac('sha256', $body, $webhook['secret']);
        
        wp_remote_post($webhook['url'], [
            'timeout'     => 5,
            'blocking'    => false, // Non-blocking
            'headers'     => [
                'Content-Type'          => 'application/json',
                'X-CC-Signature'        => $signature,
                'X-CC-Event-Type'       => $event['event_type'],
            ],
            'body'        => $body,
        ]);
    }

    // =========================================================================
    // Google Analytics 4 Integration
    // =========================================================================

    /**
     * Get GA4 configuration
     * 
     * @return array|null GA4 config or null
     */
    public function get_ga4_config() {
        return get_option(self::OPTION_GA4, null);
    }

    /**
     * Save GA4 configuration
     * 
     * @param array $config GA4 config (measurement_id, api_secret, enabled)
     */
    public function save_ga4_config($config) {
        update_option(self::OPTION_GA4, [
            'measurement_id' => sanitize_text_field($config['measurement_id']),
            'api_secret'     => sanitize_text_field($config['api_secret']),
            'enabled'        => (bool) ($config['enabled'] ?? false),
        ]);
    }

    /**
     * Dispatch event to GA4 Measurement Protocol
     * 
     * @param array $event Event data
     */
    private function dispatch_to_ga4($event) {
        $config = $this->get_ga4_config();
        
        if (!$config || !$config['enabled']) {
            return;
        }
        
        $url = sprintf(
            'https://www.google-analytics.com/mp/collect?measurement_id=%s&api_secret=%s',
            $config['measurement_id'],
            $config['api_secret']
        );
        
        // Map our event to GA4 format
        $ga4_event = $this->map_to_ga4_event($event);
        
        if (!$ga4_event) {
            return;
        }
        
        $payload = [
            'client_id' => $event['device_id_hash'], // Use hashed device ID
            'events'    => [$ga4_event],
        ];
        
        wp_remote_post($url, [
            'timeout'  => 5,
            'blocking' => false,
            'headers'  => ['Content-Type' => 'application/json'],
            'body'     => wp_json_encode($payload),
        ]);
    }

    /**
     * Map CastConductor event to GA4 event format
     * 
     * @param array $event Our event
     * @return array|null GA4 event or null if not mappable
     */
    private function map_to_ga4_event($event) {
        $type = $event['event_type'];
        $props = $event['properties'] ?? [];
        
        // Map common events
        $mappings = [
            'session_start' => [
                'name'   => 'session_start',
                'params' => [],
            ],
            'scene_view' => [
                'name'   => 'page_view',
                'params' => [
                    'page_title'    => $props['scene_name'] ?? 'Unknown',
                    'page_location' => 'roku://scene/' . ($props['scene_id'] ?? 0),
                ],
            ],
            'stream_start' => [
                'name'   => 'video_start',
                'params' => [
                    'video_title' => $props['content_name'] ?? 'Unknown',
                ],
            ],
            'stream_end' => [
                'name'   => 'video_complete',
                'params' => [
                    'video_percent' => $props['completion_percent'] ?? 0,
                ],
            ],
            'qr_scan' => [
                'name'   => 'generate_lead',
                'params' => [
                    'currency' => 'USD',
                    'value'    => 0,
                ],
            ],
        ];
        
        if (!isset($mappings[$type])) {
            return null;
        }
        
        return $mappings[$type];
    }

    // =========================================================================
    // Segment Integration
    // =========================================================================

    /**
     * Get Segment configuration
     * 
     * @return array|null Segment config or null
     */
    public function get_segment_config() {
        return get_option(self::OPTION_SEGMENT, null);
    }

    /**
     * Save Segment configuration
     * 
     * @param array $config Segment config (write_key, enabled)
     */
    public function save_segment_config($config) {
        update_option(self::OPTION_SEGMENT, [
            'write_key' => sanitize_text_field($config['write_key']),
            'enabled'   => (bool) ($config['enabled'] ?? false),
        ]);
    }

    /**
     * Dispatch event to Segment HTTP API
     * 
     * @param array $event Event data
     */
    private function dispatch_to_segment($event) {
        $config = $this->get_segment_config();
        
        if (!$config || !$config['enabled']) {
            return;
        }
        
        $url = 'https://api.segment.io/v1/track';
        
        $payload = [
            'userId'     => $event['device_id_hash'],
            'event'      => $event['event_type'],
            'properties' => $event['properties'] ?? [],
            'context'    => [
                'device' => $event['context']['device'] ?? [],
                'locale' => $event['context']['geo']['country'] ?? 'unknown',
            ],
            'timestamp'  => $event['timestamp'],
        ];
        
        wp_remote_post($url, [
            'timeout'  => 5,
            'blocking' => false,
            'headers'  => [
                'Content-Type'  => 'application/json',
                'Authorization' => 'Basic ' . base64_encode($config['write_key'] . ':'),
            ],
            'body'     => wp_json_encode($payload),
        ]);
    }

    // =========================================================================
    // Partner API Keys (for external data access)
    // =========================================================================

    /**
     * Create a partner API key
     * 
     * @param array $config Key config (name, permissions, rate_limit, expires_at)
     * @return array Key details including the plain-text key (shown once)
     */
    public function create_partner_key($config) {
        global $wpdb;
        
        // Generate key
        $key = 'cc_partner_' . bin2hex(random_bytes(24));
        $prefix = substr($key, 0, 16);
        $hash = hash('sha256', $key);
        
        $table = CC_Analytics_Database::table(CC_Analytics_Database::TABLE_API_KEYS);
        
        $wpdb->insert($table, [
            'key_hash'    => $hash,
            'key_prefix'  => $prefix,
            'name'        => sanitize_text_field($config['name']),
            'permissions' => wp_json_encode($config['permissions'] ?? ['read']),
            'rate_limit'  => (int) ($config['rate_limit'] ?? 1000),
            'ip_whitelist'=> isset($config['ip_whitelist']) ? wp_json_encode($config['ip_whitelist']) : null,
            'expires_at'  => $config['expires_at'] ?? null,
            'created_by'  => get_current_user_id(),
            'created_at'  => CC_Analytics_Helpers::now_utc(),
        ], ['%s', '%s', '%s', '%s', '%d', '%s', '%s', '%d', '%s']);
        
        return [
            'id'      => $wpdb->insert_id,
            'key'     => $key, // Plain text - show once!
            'prefix'  => $prefix,
            'name'    => $config['name'],
        ];
    }

    /**
     * Validate a partner API key
     * 
     * @param string $key Plain-text API key
     * @return array|false Key data or false if invalid
     */
    public function validate_partner_key($key) {
        global $wpdb;
        
        $hash = hash('sha256', $key);
        $table = CC_Analytics_Database::table(CC_Analytics_Database::TABLE_API_KEYS);
        
        $row = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE key_hash = %s",
            $hash
        ), ARRAY_A);
        
        if (!$row) {
            return false;
        }
        
        // Check expiration
        if ($row['expires_at'] && strtotime($row['expires_at']) < time()) {
            return false;
        }
        
        // Update last used
        $wpdb->update($table, [
            'last_used_at' => CC_Analytics_Helpers::now_utc(),
        ], ['id' => $row['id']], ['%s'], ['%d']);
        
        return [
            'id'          => $row['id'],
            'name'        => $row['name'],
            'permissions' => json_decode($row['permissions'], true),
            'rate_limit'  => $row['rate_limit'],
        ];
    }

    /**
     * List all partner keys (without revealing the keys)
     * 
     * @return array List of keys
     */
    public function list_partner_keys() {
        global $wpdb;
        
        $table = CC_Analytics_Database::table(CC_Analytics_Database::TABLE_API_KEYS);
        
        return $wpdb->get_results(
            "SELECT id, key_prefix, name, permissions, rate_limit, expires_at, last_used_at, created_at
            FROM {$table}
            ORDER BY created_at DESC",
            ARRAY_A
        );
    }

    /**
     * Revoke a partner key
     * 
     * @param int $id Key ID
     */
    public function revoke_partner_key($id) {
        global $wpdb;
        
        $table = CC_Analytics_Database::table(CC_Analytics_Database::TABLE_API_KEYS);
        $wpdb->delete($table, ['id' => $id], ['%d']);
    }
}
