<?php

namespace WPUltimateSecurity\UltimateSecurity\Presentation\API\Controllers;

use WP_REST_Request;
use WP_REST_Response;
use WPUltimateSecurity\UltimateSecurity\Support\Helpers\DateHelper;

/**
 * Site Status Controller
 *
 * Handles SSL certificate and uptime/response time status endpoints
 */
class SiteStatusController
{
    /**
     * Get combined site status (SSL + uptime)
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function get_site_status(WP_REST_Request $request)
    {
        $force_refresh = isset($request['force_refresh']) ? (bool) $request['force_refresh'] : false;

        // Check cache first (cache for 5 minutes)
        if (!$force_refresh) {
            $cached = get_transient('ultimate_security_site_status');
            if ($cached !== false) {
                return new WP_REST_Response($cached, 200);
            }
        }

        $response_data = [
            'ssl' => self::get_ssl_status(),
            'uptime' => self::get_uptime_status(),
        ];

        // Cache for 5 minutes
        set_transient('ultimate_security_site_status', $response_data, 5 * MINUTE_IN_SECONDS);

        return new WP_REST_Response($response_data, 200);
    }

    /**
     * Get SSL certificate status
     *
     * @return array
     */
    private static function get_ssl_status()
    {
        $site_url = site_url();
        $is_https = is_ssl();

        $ssl_info = [
            'enabled' => $is_https,
            'certificate' => null,
            'grade' => 'N/A',
        ];

        if (!$is_https) {
            $ssl_info['grade'] = 'F';
            return $ssl_info;
        }

        // Parse the domain from site URL
        $parsed = wp_parse_url($site_url);
        $host = $parsed['host'] ?? '';

        if (empty($host)) {
            return $ssl_info;
        }

        // Get SSL certificate info using stream context
        $context = stream_context_create([
            'ssl' => [
                'capture_peer_cert' => true,
                'verify_peer' => false,
                'verify_peer_name' => false,
            ]
        ]);

        $socket = @stream_socket_client(
            "ssl://{$host}:443",
            $errno,
            $errstr,
            10,
            STREAM_CLIENT_CONNECT,
            $context
        );

        if (!$socket) {
            // Connection failed, but HTTPS is enabled
            $ssl_info['grade'] = 'B';
            $ssl_info['error'] = 'Could not connect to verify certificate';
            return $ssl_info;
        }

        $params = stream_context_get_params($socket);
        fclose($socket);

        if (!isset($params['options']['ssl']['peer_certificate'])) {
            $ssl_info['grade'] = 'B';
            return $ssl_info;
        }

        $cert = openssl_x509_parse($params['options']['ssl']['peer_certificate']);

        if (!$cert) {
            $ssl_info['grade'] = 'B';
            return $ssl_info;
        }

        $valid_from = $cert['validFrom_time_t'] ?? 0;
        $valid_to = $cert['validTo_time_t'] ?? 0;
        $issuer = $cert['issuer']['O'] ?? ($cert['issuer']['CN'] ?? 'Unknown');
        $days_remaining = max(0, floor(($valid_to - time()) / 86400));
        $is_valid = $valid_to > time() && $valid_from < time();

        $ssl_info['certificate'] = [
            'issuer' => sanitize_text_field($issuer),
            'valid_from' => gmdate('Y-m-d', $valid_from),
            'valid_to' => gmdate('Y-m-d', $valid_to),
            'days_remaining' => (int) $days_remaining,
            'is_valid' => $is_valid,
        ];

        // Calculate grade based on days remaining
        if (!$is_valid) {
            $ssl_info['grade'] = 'F';
        } elseif ($days_remaining > 30) {
            $ssl_info['grade'] = 'A';
        } elseif ($days_remaining > 14) {
            $ssl_info['grade'] = 'B';
        } elseif ($days_remaining > 7) {
            $ssl_info['grade'] = 'C';
        } else {
            $ssl_info['grade'] = 'D';
        }

        return $ssl_info;
    }

    /**
     * Get uptime/response time status
     *
     * @return array
     */
    private static function get_uptime_status()
    {
        $site_url = site_url();
        $start_time = microtime(true);

        $response = wp_remote_get($site_url, [
            'timeout' => 15,
            'sslverify' => false,
            'redirection' => 0,
            'blocking' => true,
        ]);

        $response_time = round((microtime(true) - $start_time) * 1000); // Convert to ms

        if (is_wp_error($response)) {
            return [
                'status' => 'down',
                'response_time' => null,
                'http_code' => null,
                'error' => $response->get_error_message(),
                'checked_at' => DateHelper::now(),
            ];
        }

        $http_code = wp_remote_retrieve_response_code($response);

        // Determine status based on HTTP code and response time
        $status = 'up';
        if ($http_code >= 500) {
            $status = 'down';
        } elseif ($http_code >= 400 || $response_time > 3000) {
            $status = 'degraded';
        }

        return [
            'status' => $status,
            'response_time' => (int) $response_time,
            'http_code' => (int) $http_code,
            'checked_at' => DateHelper::now(),
        ];
    }
}
