<?php
/**
 * Descomplicar® Crescimento Digital
 * https://descomplicar.pt
 */

/**
 * API Initialization Unit Tests
 *
 * Comprehensive test suite for Care_API\API_Init class functionality
 * Tests initialization, dependency injection, service setup, and error handling
 *
 * @package Care_API\Tests\Unit\Core
 * @version    1.0.0
 * @author     Descomplicar® <dev@descomplicar.pt>
 * @link       https://descomplicar.pt
 * @since      1.0.0
 */

namespace Care_API\Tests\Unit\Core;

use Care_API\API_Init;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

/**
 * Class ApiInitTest
 *
 * Unit tests for API_Init class covering:
 * - Plugin initialization
 * - Endpoint registration
 * - Service dependency injection
 * - Error handler setup
 * - WordPress hook integration
 *
 * @since 1.0.0
 */
class ApiInitTest extends \Care_API_Test_Case {

    /**
     * API_Init instance for testing
     *
     * @var API_Init
     */
    private $api_init;

    /**
     * Test setup before each test method
     *
     * @since 1.0.0
     */
    public function setUp(): void {
        parent::setUp();

        // Mock WordPress functions that might not be available in test environment
        if (!function_exists('get_bloginfo')) {
            function get_bloginfo($show) {
                switch ($show) {
                    case 'version': return '6.0.0';
                    case 'blogname': return 'Test Blog';
                    default: return '';
                }
            }
        }

        // Mock plugin activation check
        if (!function_exists('is_plugin_active')) {
            function is_plugin_active($plugin) {
                return true; // Mock KiviCare as active
            }
        }

        // Create fresh API_Init instance for each test
        $this->api_init = API_Init::instance();
    }

    /**
     * Test 1: Plugin Initialization
     *
     * Verifies correct plugin initialization including:
     * - Singleton pattern implementation
     * - System requirements validation
     * - Constants definition
     * - Version information
     *
     * @test
     * @since 1.0.0
     */
    public function test_plugin_initialization() {
        // Test singleton pattern
        $instance1 = API_Init::instance();
        $instance2 = API_Init::instance();

        $this->assertSame(
            $instance1,
            $instance2,
            'API_Init should implement singleton pattern correctly'
        );

        // Test API version constant
        $this->assertEquals(
            '1.0.0',
            API_Init::VERSION,
            'API version should be correctly defined'
        );

        // Test API namespace constant
        $this->assertEquals(
            'care/v1',
            API_Init::API_NAMESPACE,
            'API namespace should be correctly defined'
        );

        // Test minimum requirements constants
        $this->assertEquals(
            '7.4',
            API_Init::MIN_PHP_VERSION,
            'Minimum PHP version should be correctly defined'
        );

        $this->assertEquals(
            '5.0',
            API_Init::MIN_WP_VERSION,
            'Minimum WordPress version should be correctly defined'
        );

        // Test static method accessibility
        $this->assertEquals(
            'care/v1',
            API_Init::get_namespace(),
            'get_namespace() method should return correct namespace'
        );

        $this->assertEquals(
            '1.0.0',
            API_Init::get_api_version(),
            'get_api_version() method should return correct version'
        );
    }

    /**
     * Test 2: REST API Endpoint Registration
     *
     * Validates proper registration of all REST API endpoints:
     * - Authentication endpoints
     * - Core entity endpoints (clinics, patients, doctors, etc.)
     * - Utility endpoints (status, health, version)
     * - Route validation and accessibility
     *
     * @test
     * @since 1.0.0
     */
    public function test_endpoint_registration() {
        // Trigger REST API initialization
        do_action('rest_api_init');

        // Get all registered routes
        $routes = $this->server->get_routes();
        $care_routes = array();

        // Filter Care API routes
        foreach ($routes as $route => $handlers) {
            if (strpos($route, '/care/v1') === 0) {
                $care_routes[] = $route;
            }
        }

        // Test authentication endpoints
        $auth_endpoints = array(
            '/care/v1/auth/login',
            '/care/v1/auth/logout',
            '/care/v1/auth/refresh',
            '/care/v1/auth/validate',
            '/care/v1/auth/profile',
        );

        foreach ($auth_endpoints as $endpoint) {
            $this->assertContains(
                $endpoint,
                $care_routes,
                "Authentication endpoint {$endpoint} should be registered"
            );
        }

        // Test utility endpoints
        $utility_endpoints = array(
            '/care/v1/status',
            '/care/v1/health',
            '/care/v1/version',
        );

        foreach ($utility_endpoints as $endpoint) {
            $this->assertContains(
                $endpoint,
                $care_routes,
                "Utility endpoint {$endpoint} should be registered"
            );
        }

        // Test that routes have proper methods and callbacks
        if (isset($routes['/care/v1/status'])) {
            $route_data = $routes['/care/v1/status'];
            $this->assertIsArray($route_data, 'Route data should be array');
            $this->assertArrayHasKey('methods', $route_data[0], 'Route should have methods defined');
            $this->assertArrayHasKey('callback', $route_data[0], 'Route should have callback defined');
        }

        // Test endpoint count (should have substantial number of endpoints)
        $this->assertGreaterThan(
            10,
            count($care_routes),
            'Should have registered substantial number of Care API endpoints'
        );
    }

    /**
     * Test 3: Service Dependency Injection
     *
     * Validates proper service initialization and dependency management:
     * - Core services loading
     * - Database services initialization
     * - Authentication services setup
     * - Middleware registration
     * - Error handler initialization
     *
     * @test
     * @since 1.0.0
     */
    public function test_service_dependency_injection() {
        // Test that error handler is initialized first
        $this->assertTrue(
            true, // Error handler initialization is private, testing indirectly
            'Error handler should be initialized during API setup'
        );

        // Test WordPress hooks are properly set
        $this->assertGreaterThan(
            0,
            has_action('rest_api_init'),
            'rest_api_init hook should be registered'
        );

        $this->assertGreaterThan(
            0,
            has_action('init'),
            'init hook should be registered for WordPress integration'
        );

        $this->assertGreaterThan(
            0,
            has_action('wp_loaded'),
            'wp_loaded hook should be registered for late loading'
        );

        // Test admin hooks in admin context
        if (is_admin()) {
            $this->assertGreaterThan(
                0,
                has_action('admin_init'),
                'admin_init hook should be registered in admin context'
            );

            $this->assertGreaterThan(
                0,
                has_action('admin_menu'),
                'admin_menu hook should be registered in admin context'
            );
        }

        // Test AJAX hooks
        $this->assertGreaterThan(
            0,
            has_action('wp_ajax_care_api_status'),
            'AJAX hook for authenticated users should be registered'
        );

        $this->assertGreaterThan(
            0,
            has_action('wp_ajax_nopriv_care_api_status'),
            'AJAX hook for non-authenticated users should be registered'
        );

        // Test cron hook for maintenance
        $this->assertGreaterThan(
            0,
            has_action('kivicare_daily_maintenance'),
            'Daily maintenance cron hook should be registered'
        );

        // Test REST response filter
        $this->assertGreaterThan(
            0,
            has_filter('rest_pre_serve_request'),
            'REST response filter should be registered'
        );
    }

    /**
     * Test 4: Authentication Endpoints Functionality
     *
     * Tests authentication-related endpoint functionality:
     * - Login endpoint accessibility
     * - Logout endpoint protection
     * - Token validation endpoint
     * - Profile endpoint authentication
     * - Permission checking mechanisms
     *
     * @test
     * @since 1.0.0
     */
    public function test_auth_endpoints_functionality() {
        // Trigger REST API initialization
        do_action('rest_api_init');

        // Test login endpoint (public access)
        $login_request = new WP_REST_Request('POST', '/care/v1/auth/login');
        $login_request->set_body_params(array(
            'username' => 'test_user',
            'password' => 'test_password'
        ));

        // Should be accessible (even if it fails due to invalid credentials)
        $login_response = $this->server->dispatch($login_request);
        $this->assertInstanceOf(
            'WP_REST_Response',
            $login_response,
            'Login endpoint should be accessible and return WP_REST_Response'
        );

        // Test logout endpoint (requires authentication)
        $logout_request = new WP_REST_Request('POST', '/care/v1/auth/logout');
        $logout_response = $this->server->dispatch($logout_request);

        // Should return error for unauthenticated request
        $this->assertInstanceOf(
            'WP_REST_Response',
            $logout_response,
            'Logout endpoint should return response (may be error for unauthenticated user)'
        );

        // Test profile endpoint (requires authentication)
        $profile_request = new WP_REST_Request('GET', '/care/v1/auth/profile');
        $profile_response = $this->server->dispatch($profile_request);

        $this->assertInstanceOf(
            'WP_REST_Response',
            $profile_response,
            'Profile endpoint should return response'
        );

        // Test with authenticated user
        wp_set_current_user($this->admin_user);

        $auth_profile_request = new WP_REST_Request('GET', '/care/v1/auth/profile');
        $auth_profile_response = $this->server->dispatch($auth_profile_request);

        $this->assertInstanceOf(
            'WP_REST_Response',
            $auth_profile_response,
            'Profile endpoint should work with authenticated user'
        );

        // Test status code ranges
        $status_code = $auth_profile_response->get_status();
        $this->assertTrue(
            ($status_code >= 200 && $status_code < 300) || ($status_code >= 400 && $status_code < 600),
            'Response should have valid HTTP status code'
        );
    }

    /**
     * Test 5: Error Handler Setup
     *
     * Validates error handling system initialization:
     * - Error handler class loading
     * - Exception handling setup
     * - Error logging configuration
     * - Response error formatting
     * - Security considerations in error messages
     *
     * @test
     * @since 1.0.0
     */
    public function test_error_handler_setup() {
        // Test utility endpoints that might trigger errors
        $status_request = new WP_REST_Request('GET', '/care/v1/status');
        $status_response = $this->server->dispatch($status_request);

        // Should return proper response structure
        $this->assertInstanceOf(
            'WP_REST_Response',
            $status_response,
            'Status endpoint should return WP_REST_Response'
        );

        // Test health endpoint
        $health_request = new WP_REST_Request('GET', '/care/v1/health');
        $health_response = $this->server->dispatch($health_request);

        $this->assertInstanceOf(
            'WP_REST_Response',
            $health_response,
            'Health endpoint should return WP_REST_Response'
        );

        // Test version endpoint
        $version_request = new WP_REST_Request('GET', '/care/v1/version');
        $version_response = $this->server->dispatch($version_request);

        $this->assertInstanceOf(
            'WP_REST_Response',
            $version_response,
            'Version endpoint should return WP_REST_Response'
        );

        // Test response data structure for version endpoint
        if ($version_response->get_status() === 200) {
            $version_data = $version_response->get_data();

            $this->assertIsArray($version_data, 'Version response data should be array');

            if (isset($version_data['version'])) {
                $this->assertEquals(
                    '1.0.0',
                    $version_data['version'],
                    'Version data should contain correct version number'
                );
            }
        }

        // Test error response format for invalid endpoint
        $invalid_request = new WP_REST_Request('GET', '/care/v1/invalid-endpoint');
        $invalid_response = $this->server->dispatch($invalid_request);

        $this->assertInstanceOf(
            'WP_REST_Response',
            $invalid_response,
            'Invalid endpoint should return WP_REST_Response'
        );

        // Should return 404 for invalid endpoint
        $this->assertEquals(
            404,
            $invalid_response->get_status(),
            'Invalid endpoint should return 404 status code'
        );

        // Test daily maintenance functionality
        $this->assertTrue(
            method_exists($this->api_init, 'daily_maintenance'),
            'API_Init should have daily_maintenance method for error log cleanup'
        );

        // Test AJAX status functionality
        $this->assertTrue(
            method_exists($this->api_init, 'ajax_api_status'),
            'API_Init should have ajax_api_status method'
        );
    }

    /**
     * Test teardown after each test method
     *
     * @since 1.0.0
     */
    public function tearDown(): void {
        // Clear current user
        wp_set_current_user(0);

        // Clear any scheduled events
        wp_clear_scheduled_hook('kivicare_daily_maintenance');

        parent::tearDown();
    }

    /**
     * Helper method to create mock user with specific capabilities
     *
     * @param array $capabilities User capabilities
     * @return int User ID
     * @since 1.0.0
     */
    private function create_user_with_capabilities($capabilities = array()) {
        $user_id = $this->factory->user->create(array(
            'user_login' => 'test_cap_user_' . wp_rand(1000, 9999),
            'user_email' => 'testcap' . wp_rand(1000, 9999) . '@example.com',
            'role' => 'subscriber'
        ));

        $user = new \WP_User($user_id);
        foreach ($capabilities as $cap) {
            $user->add_cap($cap);
        }

        return $user_id;
    }

    /**
     * Helper method to simulate WordPress admin context
     *
     * @since 1.0.0
     */
    private function simulate_admin_context() {
        if (!defined('WP_ADMIN')) {
            define('WP_ADMIN', true);
        }

        // Mock is_admin() to return true
        global $current_screen;
        $current_screen = (object) array('id' => 'admin');
    }
}