<?php

namespace FleekDash\Services;

/**
 * Data Source Plugin Service
 *
 * Manages the plugin system for data sources in the DashboardBuilder.
 * Provides hooks and filters for third-party plugins to register custom data sources.
 */
class DataSourcePluginService
{
    /**
     * Registered data source plugins
     */
    private $plugins = [];

    /**
     * Available data source types
     */
    private $data_source_types = [];

    /**
     * Plugin hooks and filters
     */
    private $hooks = [];

    public function __construct()
    {
        $this->init_hooks();
        $this->discover_plugins();
    }

    /**
     * Initialize WordPress hooks
     */
    private function init_hooks()
    {
        // Register default data source types
        \add_action('fleekdash_register_data_source_types', [$this, 'register_default_types']);

        // Discover and load plugins
        \add_action('plugins_loaded', [$this, 'discover_plugins'], 20);

        // TODO: Migrate to V2.2 DataSourcesRoutes
        // REST API endpoint should be migrated to DataSourcesRoutes
        // \add_action('rest_api_init', [$this, 'register_rest_routes']);

        // Admin hooks - REMOVED: Data Sources menu is no longer needed
        // \add_action('admin_menu', [$this, 'add_admin_menu']);
        // \add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_scripts']);
    }

    /**
     * Register default data source types
     */
    public function register_default_types()
    {
        $this->register_data_source_type('api', [
            'name' => 'API Endpoint',
            'description' => 'Fetch data from REST API endpoints',
            'icon' => 'api',
            'config_schema' => [
                'endpoint' => [
                    'type' => 'string',
                    'required' => true,
                    'label' => 'API Endpoint URL',
                    'placeholder' => 'https://api.example.com/data'
                ],
                'method' => [
                    'type' => 'select',
                    'options' => ['GET', 'POST', 'PUT', 'DELETE'],
                    'default' => 'GET',
                    'label' => 'HTTP Method'
                ],
                'headers' => [
                    'type' => 'object',
                    'label' => 'Request Headers',
                    'description' => 'Additional headers to send with the request'
                ],
                'body' => [
                    'type' => 'object',
                    'label' => 'Request Body',
                    'description' => 'Data to send in the request body'
                ]
            ]
        ]);

        $this->register_data_source_type('wp-query', [
            'name' => 'WordPress Query',
            'description' => 'Query WordPress posts, pages, and custom post types',
            'icon' => 'database',
            'config_schema' => [
                'post_type' => [
                    'type' => 'select',
                    'options' => $this->get_post_types(),
                    'default' => 'post',
                    'label' => 'Post Type'
                ],
                'posts_per_page' => [
                    'type' => 'number',
                    'default' => 10,
                    'label' => 'Posts Per Page'
                ],
                'orderby' => [
                    'type' => 'select',
                    'options' => [
                        'date' => 'Date',
                        'title' => 'Title',
                        'ID' => 'ID',
                        'menu_order' => 'Menu Order',
                        'comment_count' => 'Comment Count'
                    ],
                    'default' => 'date',
                    'label' => 'Order By'
                ],
                'order' => [
                    'type' => 'select',
                    'options' => ['ASC', 'DESC'],
                    'default' => 'DESC',
                    'label' => 'Order'
                ]
            ]
        ]);

        $this->register_data_source_type('static', [
            'name' => 'Static Data',
            'description' => 'Use static data or configuration values',
            'icon' => 'file-text',
            'config_schema' => [
                'data' => [
                    'type' => 'array',
                    'label' => 'Static Data',
                    'description' => 'Array of data objects'
                ],
                'format' => [
                    'type' => 'select',
                    'options' => ['json', 'csv', 'xml'],
                    'default' => 'json',
                    'label' => 'Data Format'
                ]
            ]
        ]);

        $this->register_data_source_type('external', [
            'name' => 'External Integration',
            'description' => 'Data from external integrations and plugins',
            'icon' => 'external-link',
            'config_schema' => [
                'integration_id' => [
                    'type' => 'string',
                    'required' => true,
                    'label' => 'Integration ID'
                ],
                'metric' => [
                    'type' => 'string',
                    'required' => true,
                    'label' => 'Metric to fetch'
                ],
                'parameters' => [
                    'type' => 'object',
                    'label' => 'Additional Parameters'
                ]
            ]
        ]);
    }

    /**
     * Register a new data source type
     */
    public function register_data_source_type($type, $config)
    {
        $this->data_source_types[$type] = array_merge($config, [
            'type' => $type,
            'plugin' => $config['plugin'] ?? 'core'
        ]);

        // Allow plugins to modify the configuration
        $this->data_source_types[$type] = \apply_filters(
            "fleekdash_data_source_type_{$type}",
            $this->data_source_types[$type],
        );
    }

    /**
     * Register a data source plugin
     */
    public function register_plugin($plugin_id, $config)
    {
        $default_config = [
            'id' => $plugin_id,
            'name' => '',
            'description' => '',
            'version' => '1.0.0',
            'author' => '',
            'data_sources' => [],
            'hooks' => [],
            'dependencies' => [],
            'enabled' => true
        ];

        $this->plugins[$plugin_id] = array_merge($default_config, $config);

        // Register data sources from this plugin
        if (!empty($config['data_sources'])) {
            foreach ($config['data_sources'] as $source_type => $source_config) {
                $source_config['plugin'] = $plugin_id;
                $this->register_data_source_type($source_type, $source_config);
            }
        }

        // Register hooks from this plugin
        if (!empty($config['hooks'])) {
            foreach ($config['hooks'] as $hook_name => $callback) {
                $this->register_hook($hook_name, $callback, $plugin_id);
            }
        }
    }

    /**
     * Discover and load plugins
     */
    public function discover_plugins()
    {
        // Allow plugins to register themselves
        \do_action('fleekdash_register_data_source_plugins', $this);

        // Discover plugins from mu-plugins directory
        $this->discover_mu_plugins();

        // Discover plugins from plugins directory
        $this->discover_standard_plugins();

        // Validate plugin dependencies
        $this->validate_plugin_dependencies();
    }

    /**
     * Discover MU plugins
     */
    private function discover_mu_plugins()
    {
        $mu_plugins_dir = WPMU_PLUGIN_DIR . '/fleekdash-data-sources/';

        if (!is_dir($mu_plugins_dir)) {
            return;
        }

        $plugins = glob($mu_plugins_dir . '*/plugin.json');

        foreach ($plugins as $plugin_file) {
            $this->load_plugin_from_file($plugin_file);
        }
    }

    /**
     * Discover standard plugins
     */
    private function discover_standard_plugins()
    {
        $plugins_dir = WP_PLUGIN_DIR . '/fleekdash-data-sources/';

        if (!is_dir($plugins_dir)) {
            return;
        }

        $plugins = glob($plugins_dir . '*/plugin.json');

        foreach ($plugins as $plugin_file) {
            $this->load_plugin_from_file($plugin_file);
        }
    }

    /**
     * Load plugin from JSON file
     */
    private function load_plugin_from_file($plugin_file)
    {
        if (!file_exists($plugin_file)) {
            return;
        }

        $plugin_data = json_decode(file_get_contents($plugin_file), true);

        if (!$plugin_data || !isset($plugin_data['id'])) {
            return;
        }

        $plugin_dir = dirname($plugin_file);
        $plugin_id = $plugin_data['id'];

        // Load plugin main file if specified
        if (isset($plugin_data['main_file']) && file_exists($plugin_dir . '/' . $plugin_data['main_file'])) {
            require_once $plugin_dir . '/' . $plugin_data['main_file'];
        }

        // Register the plugin
        $this->register_plugin($plugin_id, $plugin_data);
    }

    /**
     * Validate plugin dependencies
     */
    private function validate_plugin_dependencies()
    {
        foreach ($this->plugins as $plugin_id => $plugin) {
            if (empty($plugin['dependencies'])) {
                continue;
            }

            $missing_deps = [];
            foreach ($plugin['dependencies'] as $dep) {
                if (!isset($this->plugins[$dep])) {
                    $missing_deps[] = $dep;
                }
            }

            if (!empty($missing_deps)) {
                $this->plugins[$plugin_id]['enabled'] = false;
                $this->plugins[$plugin_id]['error'] = sprintf(
                    'Missing dependencies: %s',
                    implode(', ', $missing_deps),
                );
            }
        }
    }

    /**
     * Register a hook
     */
    public function register_hook($hook_name, $callback, $plugin_id)
    {
        if (!isset($this->hooks[$hook_name])) {
            $this->hooks[$hook_name] = [];
        }

        $this->hooks[$hook_name][] = [
            'callback' => $callback,
            'plugin_id' => $plugin_id
        ];
    }

    /**
     * Execute a hook
     */
    public function execute_hook($hook_name, $data = null)
    {
        if (!isset($this->hooks[$hook_name])) {
            return $data;
        }

        foreach ($this->hooks[$hook_name] as $hook) {
            if (is_callable($hook['callback'])) {
                $data = call_user_func($hook['callback'], $data);
            }
        }

        return $data;
    }

    /**
     * Get all registered data source types
     */
    public function get_data_source_types()
    {
        return \apply_filters('fleekdash_data_source_types', $this->data_source_types);
    }

    /**
     * Get data source type configuration
     */
    public function get_data_source_type($type)
    {
        $types = $this->get_data_source_types();
        return isset($types[$type]) ? $types[$type] : null;
    }

    /**
     * Get all registered plugins
     */
    public function get_plugins()
    {
        return \apply_filters('fleekdash_data_source_plugins', $this->plugins);
    }

    /**
     * Get plugin by ID
     */
    public function get_plugin($plugin_id)
    {
        $plugins = $this->get_plugins();
        return isset($plugins[$plugin_id]) ? $plugins[$plugin_id] : null;
    }

    /**
     * Enable/disable plugin
     */
    public function set_plugin_status($plugin_id, $enabled)
    {
        if (isset($this->plugins[$plugin_id])) {
            $this->plugins[$plugin_id]['enabled'] = $enabled;
            $this->save_plugin_settings();
        }
    }

    /**
     * Get available post types for WP Query
     */
    private function get_post_types()
    {
        $post_types = \get_post_types(['public' => true], 'objects');
        $options = [];

        foreach ($post_types as $post_type => $object) {
            $options[$post_type] = $object->labels->singular_name;
        }

        return $options;
    }

    /**
     * Register REST API routes
     */
    public function register_rest_routes()
    {
        \register_rest_route('fleekdash/v1', '/data-source-plugins', [
            [
                'methods' => 'GET',
                'callback' => [$this, 'get_plugins_endpoint'],
                'permission_callback' => [$this, 'check_admin_permissions']
            ]
        ]);

        \register_rest_route('fleekdash/v1', '/data-source-types', [
            [
                'methods' => 'GET',
                'callback' => [$this, 'get_data_source_types_endpoint'],
                'permission_callback' => [$this, 'check_admin_permissions']
            ]
        ]);

        \register_rest_route('fleekdash/v1', '/data-source-plugins/(?P<plugin_id>[a-zA-Z0-9_-]+)/status', [
            [
                'methods' => 'POST',
                'callback' => [$this, 'update_plugin_status_endpoint'],
                'permission_callback' => [$this, 'check_admin_permissions']
            ]
        ]);
    }

    /**
     * REST API endpoint: Get plugins
     */
    public function get_plugins_endpoint($request)
    {
        return new \WP_REST_Response([
            'success' => true,
            'plugins' => $this->get_plugins()
        ], 200);
    }

    /**
     * REST API endpoint: Get data source types
     */
    public function get_data_source_types_endpoint($request)
    {
        return new \WP_REST_Response([
            'success' => true,
            'types' => $this->get_data_source_types()
        ], 200);
    }

    /**
     * REST API endpoint: Update plugin status
     */
    public function update_plugin_status_endpoint($request)
    {
        $plugin_id = $request->get_param('plugin_id');
        $enabled = $request->get_param('enabled');

        if (!isset($this->plugins[$plugin_id])) {
            return new \WP_Error('plugin_not_found', 'Plugin not found', ['status' => 404]);
        }

        $this->set_plugin_status($plugin_id, (bool) $enabled);

        return new \WP_REST_Response([
            'success' => true,
            'message' => sprintf('Plugin %s %s', $plugin_id, $enabled ? 'enabled' : 'disabled')
        ], 200);
    }

    /**
     * Check admin permissions
     */
    public function check_admin_permissions()
    {
        return \current_user_can('manage_options');
    }

    /**
     * Add admin menu
     */
    public function add_admin_menu()
    {
        add_submenu_page(
            'fleekdash',
            'Data Source Plugins',
            'Data Sources',
            'manage_options',
            'fleekdash-data-sources',
            [$this, 'admin_page'],
        );
    }

    /**
     * Admin page callback
     */
    public function admin_page()
    {
        include __DIR__ . '/../Admin/views/data-source-plugins.php';
    }

    /**
     * Enqueue admin scripts
     */
    public function enqueue_admin_scripts($hook)
    {
        if ($hook !== 'fleekdash_page_fleekdash-data-sources') {
            return;
        }

        \wp_enqueue_script(
            'fleekdash-data-source-plugins',
            plugin_dir_url(__FILE__) . '../../assets/js/data-source-plugins.js',
            ['jquery'],
            '1.0.0',
            true,
        );

        \wp_localize_script('fleekdash-data-source-plugins', 'fleekdashDataSources', [
            'ajaxUrl' => \admin_url('admin-ajax.php'),
            'nonce' => \wp_create_nonce('fleekdash_data_sources'),
            'restUrl' => rest_url('fleekdash/v1/')
        ]);
    }

    /**
     * Save plugin settings
     */
    private function save_plugin_settings()
    {
        $settings = [];
        foreach ($this->plugins as $plugin_id => $plugin) {
            $settings[$plugin_id] = [
                'enabled' => $plugin['enabled']
            ];
        }

        \update_option('fleekdash_data_source_plugins', $settings);
    }

    /**
     * Load plugin settings
     */
    private function load_plugin_settings()
    {
        $settings = \get_option('fleekdash_data_source_plugins', []);

        foreach ($settings as $plugin_id => $plugin_settings) {
            if (isset($this->plugins[$plugin_id])) {
                $this->plugins[$plugin_id]['enabled'] = $plugin_settings['enabled'] ?? true;
            }
        }
    }
}
