<?php

namespace WPUltimateSecurity\UltimateSecurity\Presentation\API\Controllers;

use WP_REST_Request;
use WP_REST_Response;
use WPUltimateSecurity\UltimateSecurity\Support\Helpers\DateHelper;
/**
 * Security Controller
 *
 * Handles security-related API endpoints (salts, logs, etc.)
 */
class SecurityController
{
    /**
     * Get salt keys
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function get_salt(WP_REST_Request $request)
    {
        $ultimate_security_salt_keys = [
            'AUTH_KEY' => defined('AUTH_KEY') ? AUTH_KEY : '',
            'SECURE_AUTH_KEY' => defined('SECURE_AUTH_KEY') ? SECURE_AUTH_KEY : '',
            'LOGGED_IN_KEY' => defined('LOGGED_IN_KEY') ? LOGGED_IN_KEY : '',
            'NONCE_KEY' => defined('NONCE_KEY') ? NONCE_KEY : '',
            'AUTH_SALT' => defined('AUTH_SALT') ? AUTH_SALT : '',
            'SECURE_AUTH_SALT' => defined('SECURE_AUTH_SALT') ? SECURE_AUTH_SALT : '',
            'LOGGED_IN_SALT' => defined('LOGGED_IN_SALT') ? LOGGED_IN_SALT : '',
            'NONCE_SALT' => defined('NONCE_SALT') ? NONCE_SALT : '',
        ];

        return new WP_REST_Response($ultimate_security_salt_keys, 200);
    }

    /**
     * Generate new salts
     *
     * @param WP_REST_Request $request
     * @return void
     */
    public static function generate_salts(WP_REST_Request $request)
    {

        // Array of constant names
        $keys = array(
            'AUTH_KEY',
            'SECURE_AUTH_KEY',
            'LOGGED_IN_KEY',
            'NONCE_KEY',
            'AUTH_SALT',
            'SECURE_AUTH_SALT',
            'LOGGED_IN_SALT',
            'NONCE_SALT',
        );

        // Prepare the output
        $output = '';
        foreach ($keys as $key) {
            // Generate secure random value - don't replace characters
            $random_value = wp_generate_password(64, true, true);
            // Properly escape single quotes for PHP code
            $escaped_value = addslashes($random_value);
            $output .= sprintf("define('%s', '%s');\n", $key, $escaped_value);
        }

        // Return proper REST response
        return new WP_REST_Response(
            array(
                'success' => true,
                'salts' => $output,
            ),
            200
        );
    }

    /**
     * Get salt information (last changed, next scheduled, rate limit status, preflight check)
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function get_salt_info(WP_REST_Request $request)
    {
        $last_changed = get_option('ultimate_security_rewrite_wp_config_keys_last_date', null);

        // Check rate limiting (5 minutes between regenerations)
        $can_regenerate = true;
        if ($last_changed) {
            $last_change_time = strtotime($last_changed);
            $cooldown_end = $last_change_time + (5 * 60); // 5 minutes
            $can_regenerate = time() >= $cooldown_end;
        }

        // Get next scheduled change (Pro feature)
        $next_scheduled = null;
        $upcoming_schedules = [];
        if (function_exists('wp_next_scheduled')) {
            $next_cron = wp_next_scheduled('ultimate_security_change_salt_keys');
            if ($next_cron) {
                $next_scheduled = gmdate('Y-m-d H:i:s', $next_cron);

                // Calculate next 5 scheduled changes for preview
                $options = \WPUltimateSecurity\UltimateSecurity\Support\Helpers\Utils::ultimate_security_get_option();
                $schedule_type = $options['security']['salt_change']['schedule_type'] ?? 'weekly';

                $intervals = [
                    'daily' => DAY_IN_SECONDS,
                    'weekly' => WEEK_IN_SECONDS,
                    'monthly' => 30 * DAY_IN_SECONDS,
                    'quarterly' => 90 * DAY_IN_SECONDS,
                    'biannually' => 180 * DAY_IN_SECONDS,
                    'manual' => WEEK_IN_SECONDS, // manual uses weekly
                ];

                $interval = $intervals[$schedule_type] ?? WEEK_IN_SECONDS;
                $current_time = $next_cron;

                for ($i = 0; $i < 5; $i++) {
                    $upcoming_schedules[] = gmdate('Y-m-d H:i:s', $current_time);
                    $current_time += $interval;
                }
            }
        }

        // Pre-flight check: verify wp-config.php is writable
        $wp_config_path = ABSPATH . 'wp-config.php';
        if (!file_exists($wp_config_path)) {
            $wp_config_path = dirname(ABSPATH) . '/wp-config.php';
        }
        $config_writable = file_exists($wp_config_path) && is_writable($wp_config_path);

        // Get backup salts if available
        $backup_available = (bool) get_transient('ultimate_security_salt_backup');
        $backup_expires = null;
        if ($backup_available) {
            $backup_timeout = get_option('_transient_timeout_ultimate_security_salt_backup');
            if ($backup_timeout) {
                $backup_expires = gmdate('Y-m-d H:i:s', $backup_timeout);
            }
        }

        // Check if schedule is paused (Pro feature)
        $schedule_paused_until = get_option('ultimate_security_salt_schedule_paused_until', null);
        $is_paused = $schedule_paused_until && strtotime($schedule_paused_until) > time();

        // Check if next change should be skipped
        $skip_next = get_option('ultimate_security_salt_skip_next', false);

        // Get site timezone
        $timezone_string = wp_timezone_string();

        return new WP_REST_Response([
            'last_changed_date' => $last_changed,
            'can_regenerate' => $can_regenerate,
            'next_scheduled_change' => $next_scheduled,
            'upcoming_schedules' => $upcoming_schedules,
            'config_writable' => $config_writable,
            'backup_available' => $backup_available,
            'backup_expires' => $backup_expires,
            'schedule_paused_until' => $is_paused ? $schedule_paused_until : null,
            'skip_next' => (bool) $skip_next,
            'timezone' => $timezone_string,
        ], 200);
    }

    /**
     * Get backup salt keys
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function get_salt_backup(WP_REST_Request $request)
    {
        $backup = get_transient('ultimate_security_salt_backup');

        if (!$backup) {
            return new WP_REST_Response([
                'available' => false,
                'keys' => null,
            ], 200);
        }

        return new WP_REST_Response([
            'available' => true,
            'keys' => $backup,
        ], 200);
    }

    /**
     * Restore salt keys from backup
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function restore_salt_backup(WP_REST_Request $request)
    {
        $backup = get_transient('ultimate_security_salt_backup');

        if (!$backup) {
            return new WP_REST_Response([
                'success' => false,
                'message' => __('No backup available to restore.', 'ultimate-security'),
            ], 400);
        }

        // Write the backup keys to wp-config.php
        $result = \WPUltimateSecurity\UltimateSecurity\Support\Helpers\SaltHelper::ultimate_security_write_config_keys($backup);

        if (is_wp_error($result)) {
            return new WP_REST_Response([
                'success' => false,
                'message' => $result->get_error_message(),
            ], 500);
        }

        // Clear the backup after restore
        delete_transient('ultimate_security_salt_backup');

        // Fire action hook
        do_action('ultimate_security_salt_keys_changed', 'rollback');

        return new WP_REST_Response([
            'success' => true,
            'message' => __('Salt keys restored from backup successfully.', 'ultimate-security'),
        ], 200);
    }

    /**
     * Pause scheduled salt changes until a specific date
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function pause_salt_schedule(WP_REST_Request $request)
    {
        $until_date = $request->get_param('until_date');

        if ($until_date) {
            update_option('ultimate_security_salt_schedule_paused_until', sanitize_text_field($until_date));
        } else {
            delete_option('ultimate_security_salt_schedule_paused_until');
        }

        return new WP_REST_Response([
            'success' => true,
            'paused_until' => $until_date,
        ], 200);
    }

    /**
     * Skip the next scheduled salt change
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function skip_next_salt_change(WP_REST_Request $request)
    {
        $skip = $request->get_param('skip');

        if ($skip) {
            update_option('ultimate_security_salt_skip_next', true);
        } else {
            delete_option('ultimate_security_salt_skip_next');
        }

        return new WP_REST_Response([
            'success' => true,
            'skip_next' => (bool) $skip,
        ], 200);
    }

    /**
     * Get salt change history
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function get_salt_history(WP_REST_Request $request)
    {
        global $wpdb;

        // Use component_events table (Pro's EventLogger table)
        $table_name = $wpdb->prefix . 'ultimate_security_component_events';

        // Check if table exists (Pro feature)
        if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) !== $table_name) {
            return new WP_REST_Response([], 200);
        }

        // Get salt change history entries with full details including metadata
        $results = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT id, created_at as date, object_name as trigger_type, user_id, ip_address, severity, metadata
                 FROM {$table_name}
                 WHERE event_type = %s
                 ORDER BY created_at DESC
                 LIMIT 100",
                'salt_change'
            ),
            ARRAY_A
        );

        $history = [];
        if ($results) {
            foreach ($results as $row) {
                // Get user display name
                $user_display = __('System', 'ultimate-security');
                if (!empty($row['user_id'])) {
                    $user = get_userdata($row['user_id']);
                    if ($user) {
                        $user_display = $user->display_name;
                    }
                }

                // Extract note from metadata JSON
                $note = '';
                if (!empty($row['metadata'])) {
                    $metadata = json_decode($row['metadata'], true);
                    if (is_array($metadata) && isset($metadata['note'])) {
                        $note = $metadata['note'];
                    }
                }

                $history[] = [
                    'id' => $row['id'],
                    'date' => $row['date'],
                    'trigger' => $row['trigger_type'] ?: 'manual',
                    'user_id' => $row['user_id'],
                    'user_display' => $user_display,
                    'ip_address' => $row['ip_address'] ?: '-',
                    'severity' => $row['severity'],
                    'note' => $note,
                ];
            }
        }

        return new WP_REST_Response($history, 200);
    }

    /**
     * Get login failed logs
     *
     * @param WP_REST_Request $request
     * @return WP_REST_Response
     */
    public static function get_login_failed_logs(WP_REST_Request $request)
    {
        if (!current_user_can('manage_options')) {
            return new WP_REST_Response(['message' => 'Unauthorized'], 403);
        }

        $logs = (array) get_option('ultimate_security_login_logs', []);

        // Sort logs by timestamp (latest first)
        usort($logs, function ($a, $b) {
            return ($b['timestamp'] ?? 0) <=> ($a['timestamp'] ?? 0);
        });

        $total_failed = 0;
        $recent_failed = 0;
        $now = DateHelper::timestamp();
        $day_ago = $now - DAY_IN_SECONDS;

        foreach ($logs as $entry) {
            if (!isset($entry['success'], $entry['timestamp'])) {
                continue;
            }

            if (!$entry['success']) {
                $total_failed++;
                if ($entry['timestamp'] >= $day_ago) {
                    $recent_failed++;
                }
            }
        }

        return new WP_REST_Response([
            'total_failed' => $total_failed,
            'recent_failed' => $recent_failed,
            'logs' => $logs,
        ], 200);
    }
}
