<?php
/**
 * External Data Sources Controller
 *
 * REST API controller for managing external data sources from integrations
 */

namespace FleekDash\Controllers;

defined('ABSPATH') || exit;

use FleekDash\Services\ExternalDataSourcesService;

class ExternalDataSourcesController
{
    private const ERROR_INTEGRATION_NOT_FOUND = 'Integration not found';

    private $service;

    public function __construct()
    {
        $this->service = new ExternalDataSourcesService();
    }

    /**
     * Get all external data sources
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function get_external_data_sources($request)
    {
        try {
            $response = $this->service->get_api_response();
            return \rest_ensure_response($response);
        } catch (\Exception $e) {
            return new \WP_Error(
                'external_data_sources_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Get external data sources by category
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response
     */
    public function get_external_data_sources_by_category($request)
    {
        try {
            $category = $request->get_param('category');
            $sources = $this->service->get_external_data_sources();

            // Filter by category
            $filtered_sources = array_filter($sources, function ($source) use ($category) {
                return $source['category'] === $category;
            });

            return \rest_ensure_response([
                'success' => true,
                'data' => array_values($filtered_sources),
                'count' => count($filtered_sources),
                'category' => $category,
                'timestamp' => \current_time('c'),
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'external_data_sources_category_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Get a specific external data source
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response|\WP_Error
     */
    public function get_external_data_source($request)
    {
        try {
            $source_id = $request->get_param('id');
            $sources = $this->service->get_external_data_sources();

            // Find the specific source
            $source = null;
            foreach ($sources as $s) {
                if ($s['id'] === $source_id) {
                    $source = $s;
                    break;
                }
            }

            if (!$source) {
                return new \WP_Error(
                    'external_data_source_not_found',
                    'External data source not found',
                    ['status' => 404],
                );
            }

            return \rest_ensure_response([
                'success' => true,
                'data' => $source,
                'timestamp' => \current_time('c'),
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'external_data_source_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Fetch data from an external data source
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response|\WP_Error
     */
    public function fetch_external_data($request)
    {
        try {
            $source_id = $request->get_param('source_id');
            $metric_id = $request->get_param('metric_id');
            $filters = $request->get_param('filters') ?: [];
            $time_range = $request->get_param('time_range') ?: '30d';

            // Validate required parameters
            if (!$source_id || !$metric_id) {
                return new \WP_Error(
                    'missing_parameters',
                    'Source ID and Metric ID are required',
                    ['status' => 400],
                );
            }

            // Fetch data from the external source
            $result = $this->service->fetch_external_data($source_id, $metric_id, $filters, $time_range);

            return \rest_ensure_response($result);
        } catch (\Exception $e) {
            return new \WP_Error(
                'fetch_external_data_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Test connection to an external data source
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response|\WP_Error
     */
    public function test_external_data_source_connection($request)
    {
        try {
            $source_id = $request->get_param('source_id');

            if (!$source_id) {
                return new \WP_Error(
                    'missing_source_id',
                    'Source ID is required',
                    ['status' => 400],
                );
            }

            // Get source details
            $sources = $this->service->get_external_data_sources();
            $source = null;
            foreach ($sources as $s) {
                if ($s['id'] === $source_id) {
                    $source = $s;
                    break;
                }
            }

            if (!$source) {
                return new \WP_Error(
                    'external_data_source_not_found',
                    'External data source not found',
                    ['status' => 404],
                );
            }

            // Test connection by fetching a sample metric
            $test_metric = null;
            if (!empty($source['metrics'])) {
                $test_metric = $source['metrics'][0]['id'];
            }

            if (!$test_metric) {
                return \rest_ensure_response([
                    'success' => false,
                    'error' => 'No testable metrics found',
                    'source_id' => $source_id,
                ]);
            }

            // Try to fetch data
            $result = $this->service->fetch_external_data($source_id, $test_metric, [], '24h');

            return \rest_ensure_response([
                'success' => $result['success'],
                'connection_status' => $result['success'] ? 'connected' : 'failed',
                'error' => $result['error'] ?? null,
                'source_id' => $source_id,
                'test_metric' => $test_metric,
                'timestamp' => \current_time('c'),
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'test_connection_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Get external data source metrics
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response|\WP_Error
     */
    public function get_external_data_source_metrics($request)
    {
        try {
            $source_id = $request->get_param('source_id');

            if (!$source_id) {
                return new \WP_Error(
                    'missing_source_id',
                    'Source ID is required',
                    ['status' => 400],
                );
            }

            // Get source details
            $sources = $this->service->get_external_data_sources();
            $source = null;
            foreach ($sources as $s) {
                if ($s['id'] === $source_id) {
                    $source = $s;
                    break;
                }
            }

            if (!$source) {
                return new \WP_Error(
                    'external_data_source_not_found',
                    'External data source not found',
                    ['status' => 404],
                );
            }

            return \rest_ensure_response([
                'success' => true,
                'data' => $source['metrics'] ?? [],
                'source_id' => $source_id,
                'count' => count($source['metrics'] ?? []),
                'timestamp' => \current_time('c'),
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'get_metrics_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Get external data source configuration
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response|\WP_Error
     */
    public function get_external_data_source_config($request)
    {
        try {
            $source_id = $request->get_param('source_id');

            if (!$source_id) {
                return new \WP_Error(
                    'missing_source_id',
                    'Source ID is required',
                    ['status' => 400],
                );
            }

            // Get source details
            $sources = $this->service->get_external_data_sources();
            $source = null;
            foreach ($sources as $s) {
                if ($s['id'] === $source_id) {
                    $source = $s;
                    break;
                }
            }

            if (!$source) {
                return new \WP_Error(
                    'external_data_source_not_found',
                    'External data source not found',
                    ['status' => 404],
                );
            }

            return \rest_ensure_response([
                'success' => true,
                'data' => $source['config'] ?? [],
                'source_id' => $source_id,
                'timestamp' => \current_time('c'),
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'get_config_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Update external data source configuration
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response|\WP_Error
     */
    public function update_external_data_source_config($request)
    {
        try {
            $source_id = $request->get_param('source_id');
            $config = $request->get_json_params();

            if (!$source_id) {
                return new \WP_Error(
                    'missing_source_id',
                    'Source ID is required',
                    ['status' => 400],
                );
            }

            if (!$config) {
                return new \WP_Error(
                    'missing_config',
                    'Configuration data is required',
                    ['status' => 400],
                );
            }

            // Parse source ID to get integration and source
            $parts = explode('_', $source_id, 2);
            if (count($parts) !== 2) {
                return new \WP_Error(
                    'invalid_source_id',
                    'Invalid source ID format',
                    ['status' => 400],
                );
            }

            [$integration_id, $actual_source_id] = $parts;

            // Validate integration_id to prevent path traversal (only alphanumeric, hyphen, underscore)
            if (!\preg_match('/^[a-zA-Z0-9_-]+$/', $integration_id)) {
                return new \WP_Error(
                    'invalid_integration_id',
                    'Invalid integration ID format',
                    ['status' => 400],
                );
            }

            // Update configuration in integration config file (validated path)
            $integrations_base = \realpath(FLEEKDASH_PLUGIN_DIR . 'integrations');
            if (!$integrations_base) {
                return new \WP_Error(
                    'integration_not_found',
                    self::ERROR_INTEGRATION_NOT_FOUND,
                    ['status' => 404],
                );
            }
            $config_dir = $integrations_base . \DIRECTORY_SEPARATOR . $integration_id;
            $resolved_path = \realpath($config_dir);
            if (!$resolved_path || !\str_starts_with($resolved_path, $integrations_base)) {
                return new \WP_Error(
                    'integration_not_found',
                    self::ERROR_INTEGRATION_NOT_FOUND,
                    ['status' => 404],
                );
            }
            $config_path = $resolved_path . '/config.json';
            if (!\file_exists($config_path)) {
                return new \WP_Error(
                    'integration_not_found',
                    self::ERROR_INTEGRATION_NOT_FOUND,
                    ['status' => 404],
                );
            }

            $integration_config = json_decode(file_get_contents($config_path), true);
            if (!$integration_config) {
                return new \WP_Error(
                    'invalid_integration_config',
                    'Invalid integration configuration',
                    ['status' => 500],
                );
            }

            // Find and update the data source configuration
            $updated = false;
            foreach ($integration_config['data_sources'] ?? [] as &$data_source) {
                if ($data_source['id'] === $actual_source_id) {
                    $data_source['config'] = array_merge($data_source['config'] ?? [], $config);
                    $updated = true;
                    break;
                }
            }

            if (!$updated) {
                return new \WP_Error(
                    'data_source_not_found',
                    'Data source not found in integration',
                    ['status' => 404],
                );
            }

            // Save updated configuration (config_path validated above)
            $result = \file_put_contents($config_path, \json_encode($integration_config, \JSON_PRETTY_PRINT));
            if ($result === false) {
                return new \WP_Error(
                    'config_save_failed',
                    'Failed to save configuration',
                    ['status' => 500],
                );
            }

            return \rest_ensure_response([
                'success' => true,
                'message' => 'Configuration updated successfully',
                'source_id' => $source_id,
                'timestamp' => \current_time('c'),
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'update_config_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }

    /**
     * Refresh external data sources
     *
     * @param \WP_REST_Request $request
     * @return \WP_REST_Response|\WP_Error
     */
    public function refresh_external_data_sources($request)
    {
        try {
            // Force refresh by clearing any cached data
            // The service will re-fetch from integrations

            $response = $this->service->get_api_response();

            return \rest_ensure_response([
                'success' => true,
                'message' => 'External data sources refreshed successfully',
                'data' => $response['data'],
                'count' => $response['count'],
                'timestamp' => \current_time('c'),
            ]);
        } catch (\Exception $e) {
            return new \WP_Error(
                'refresh_error',
                $e->getMessage(),
                ['status' => 500],
            );
        }
    }
}
