<?php
/**
 * Ticket Tailor Security Logger
 *
 * Logs security events and sends alerts
 * SECURITY ENHANCEMENT: Complete audit trail for compliance
 */

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}

class Ticket_Tailor_Security_Logger {

    /**
     * Table name
     */
    private $table;

    /**
     * Constructor
     */
    public function __construct() {
        global $wpdb;
        $this->table = $wpdb->prefix . 'ticket_tailor_security_log';

        // Create table if needed
        $this->maybe_create_table();
    }

    /**
     * Create security log table
     */
    private function maybe_create_table() {
        global $wpdb;

        // Check if table already exists
        $table_exists = $wpdb->get_var($wpdb->prepare(
            "SHOW TABLES LIKE %s",
            $this->table
        ));

        if ($table_exists) {
            return;
        }

        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE IF NOT EXISTS {$this->table} (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            event_type varchar(50) NOT NULL,
            user_id bigint(20) DEFAULT 0,
            ip_address varchar(45) NOT NULL,
            details longtext,
            timestamp datetime NOT NULL,
            PRIMARY KEY (id),
            KEY event_type (event_type),
            KEY timestamp (timestamp),
            KEY ip_address (ip_address)
        ) {$charset_collate};";

        // Only require upgrade.php if we actually need to create the table
        if (!function_exists('dbDelta')) {
            require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        }
        dbDelta($sql);
    }

    /**
     * Log security event
     */
    public function log_event($event_type, $details = array()) {
        global $wpdb;

        $wpdb->insert(
            $this->table,
            array(
                'event_type' => sanitize_key($event_type),
                'user_id' => get_current_user_id(),
                'ip_address' => $this->get_ip(),
                'details' => wp_json_encode($details),
                'timestamp' => current_time('mysql', 1),
            ),
            array('%s', '%d', '%s', '%s', '%s')
        );
    }

    /**
     * Log failed webhook
     */
    public function log_failed_webhook($ip, $reason) {
        $this->log_event('webhook_failed', array(
            'ip' => $ip,
            'reason' => $reason,
        ));

        // Check for multiple failures
        $recent_failures = $this->count_recent_events('webhook_failed', 300);
        if ($recent_failures >= 5) {
            $this->send_security_alert('Multiple Failed Webhook Attempts', array(
                'count' => $recent_failures,
                'ip' => $ip,
                'timeframe' => '5 minutes',
            ));
        }
    }

    /**
     * Log successful webhook
     */
    public function log_successful_webhook($ip, $event_type) {
        $this->log_event('webhook_success', array(
            'ip' => $ip,
            'webhook_type' => $event_type,
        ));
    }

    /**
     * Log API key change
     */
    public function log_api_key_change($old_key_hash, $new_key_hash) {
        $this->log_event('api_key_changed', array(
            'old_hash' => substr($old_key_hash, 0, 10),
            'new_hash' => substr($new_key_hash, 0, 10),
            'user' => wp_get_current_user()->user_login,
        ));

        $this->send_security_alert('API Key Changed', array(
            'changed_by' => wp_get_current_user()->user_login,
            'ip' => $this->get_ip(),
        ));
    }

    /**
     * Log settings change
     */
    public function log_settings_change($setting_name, $old_value = null, $new_value = null) {
        $this->log_event('settings_changed', array(
            'setting' => $setting_name,
            'changed_by' => wp_get_current_user()->user_login,
            'has_old' => !is_null($old_value),
            'has_new' => !is_null($new_value),
        ));
    }

    /**
     * Log failed login attempt
     */
    public function log_failed_login($username) {
        $this->log_event('login_failed', array(
            'username' => $username,
        ));

        // Check for brute force
        $recent_failures = $this->count_recent_events('login_failed', 900, $this->get_ip());
        if ($recent_failures >= 5) {
            $this->send_security_alert('Multiple Failed Login Attempts', array(
                'count' => $recent_failures,
                'ip' => $this->get_ip(),
                'username' => $username,
            ));
        }
    }

    /**
     * Log rate limit exceeded
     */
    public function log_rate_limit_exceeded($ip, $context = 'webhook') {
        $this->log_event('rate_limit_exceeded', array(
            'ip' => $ip,
            'context' => $context,
        ));
    }

    /**
     * Log unauthorized access attempt
     */
    public function log_unauthorized_access($resource) {
        $this->log_event('unauthorized_access', array(
            'resource' => $resource,
            'user_id' => get_current_user_id(),
        ));
    }

    /**
     * Count recent events
     */
    private function count_recent_events($event_type, $seconds, $ip = null) {
        global $wpdb;

        $time_threshold = gmdate('Y-m-d H:i:s', time() - $seconds);

        if ($ip) {
            return $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$this->table}
                WHERE event_type = %s AND timestamp > %s AND ip_address = %s",
                $event_type,
                $time_threshold,
                $ip
            ));
        } else {
            return $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$this->table}
                WHERE event_type = %s AND timestamp > %s",
                $event_type,
                $time_threshold
            ));
        }
    }

    /**
     * Send security alert email
     */
    public function send_security_alert($event_type, $details) {
        // Check if alerts are enabled
        if (!get_option('ticket_tailor_security_alerts', true)) {
            return;
        }

        $admin_email = get_option('admin_email');
        $site_name = get_bloginfo('name');
        $site_url = get_bloginfo('url');

        $subject = sprintf(
            '[%s] Security Alert: %s',
            $site_name,
            $event_type
        );

        $message = sprintf(
            "Security Event Detected on %s\n\n" .
            "Event Type: %s\n" .
            "Time: %s UTC\n" .
            "IP Address: %s\n" .
            "User: %s\n\n" .
            "Details:\n%s\n\n" .
            "---\n" .
            "This is an automated security alert from Ticket Tailor plugin.\n" .
            "To disable these alerts, go to: %s/wp-admin/admin.php?page=ticket-tailor-settings",
            $site_name,
            $event_type,
            current_time('Y-m-d H:i:s'),
            $this->get_ip(),
            wp_get_current_user()->user_login ?: 'Guest',
            $this->format_details($details),
            $site_url
        );

        wp_mail($admin_email, $subject, $message);
    }

    /**
     * Format details for email
     */
    private function format_details($details) {
        $formatted = '';
        foreach ($details as $key => $value) {
            $formatted .= '  ' . ucfirst(str_replace('_', ' ', $key)) . ': ' . $value . "\n";
        }
        return $formatted;
    }

    /**
     * Get client IP
     */
    private function get_ip() {
        $ip_keys = array(
            'HTTP_CF_CONNECTING_IP',
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_REAL_IP',
            'REMOTE_ADDR',
        );

        foreach ($ip_keys as $key) {
            if (!empty($_SERVER[$key])) {
                $ip = $_SERVER[$key];

                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }

                if (filter_var($ip, FILTER_VALIDATE_IP)) {
                    return $ip;
                }
            }
        }

        return '0.0.0.0';
    }

    /**
     * Get recent security events
     */
    public function get_recent_events($limit = 50, $event_type = null) {
        global $wpdb;

        if ($event_type) {
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM {$this->table}
                WHERE event_type = %s
                ORDER BY timestamp DESC
                LIMIT %d",
                $event_type,
                $limit
            ));
        } else {
            return $wpdb->get_results($wpdb->prepare(
                "SELECT * FROM {$this->table}
                ORDER BY timestamp DESC
                LIMIT %d",
                $limit
            ));
        }
    }

    /**
     * Clean old logs (older than 90 days)
     */
    public function cleanup_old_logs() {
        global $wpdb;

        $threshold = gmdate('Y-m-d H:i:s', time() - (90 * DAY_IN_SECONDS));

        $wpdb->query($wpdb->prepare(
            "DELETE FROM {$this->table} WHERE timestamp < %s",
            $threshold
        ));
    }

    /**
     * Get security statistics
     */
    public function get_statistics($days = 30) {
        global $wpdb;

        $threshold = gmdate('Y-m-d H:i:s', time() - ($days * DAY_IN_SECONDS));

        $stats = array();

        // Total events
        $stats['total_events'] = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$this->table} WHERE timestamp > %s",
            $threshold
        ));

        // Events by type
        $stats['by_type'] = $wpdb->get_results($wpdb->prepare(
            "SELECT event_type, COUNT(*) as count
            FROM {$this->table}
            WHERE timestamp > %s
            GROUP BY event_type
            ORDER BY count DESC",
            $threshold
        ), ARRAY_A);

        // Top IPs
        $stats['top_ips'] = $wpdb->get_results($wpdb->prepare(
            "SELECT ip_address, COUNT(*) as count
            FROM {$this->table}
            WHERE timestamp > %s
            GROUP BY ip_address
            ORDER BY count DESC
            LIMIT 10",
            $threshold
        ), ARRAY_A);

        return $stats;
    }
}
