<?php

namespace Bricksforge\ProForms;

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

class ProFormsLogger
{
    const LOG_OPTION_KEY = 'brf_logs';
    const MAX_LOGS = 1000; // Maximum number of logs to keep

    /**
     * Log a Pro Forms action
     *
     * @param string $action The action name (e.g., 'email', 'create_post', etc.)
     * @param string $level Log level ('info', 'warning', 'error', 'debug')
     * @param string $message The log message
     * @param array $context Additional context data
     * @param int|null $form_id The form ID
     * @param int|null $post_id The post ID where the form is located
     */
    public static function log($action, $level, $message, $context = [], $form_id = null, $post_id = null)
    {
        // Check if logging is enabled
        $logging_enabled = get_option('brf_logging_enabled', true);
        if (!$logging_enabled) {
            return; // Logging disabled, exit early
        }

        $log_entry = [
            'timestamp' => current_time('mysql'),
            'level' => $level,
            'action' => $action,
            'message' => $message,
            'form_id' => $form_id,
            'post_id' => $post_id,
            'context' => $context,
            'user_id' => get_current_user_id(),
            'ip_address' => self::get_client_ip(),
            'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field($_SERVER['HTTP_USER_AGENT']) : '',
        ];

        self::store_log($log_entry);
    }

    /**
     * Log successful action
     */
    public static function log_success($action, $message, $context = [], $form_id = null, $post_id = null)
    {
        self::log($action, 'info', $message, $context, $form_id, $post_id);
    }

    /**
     * Log warning
     */
    public static function log_warning($action, $message, $context = [], $form_id = null, $post_id = null)
    {
        self::log($action, 'warning', $message, $context, $form_id, $post_id);
    }

    /**
     * Log error
     */
    public static function log_error($action, $message, $context = [], $form_id = null, $post_id = null)
    {
        self::log($action, 'error', $message, $context, $form_id, $post_id);
    }

    /**
     * Log debug information
     */
    public static function log_debug($action, $message, $context = [], $form_id = null, $post_id = null)
    {
        self::log($action, 'debug', $message, $context, $form_id, $post_id);
    }

    /**
     * Store log entry in wp_options
     */
    private static function store_log($log_entry)
    {
        $logs = get_option(self::LOG_OPTION_KEY, []);

        // Ensure logs is an array
        if (!is_array($logs)) {
            $logs = [];
        }

        // Add new log entry at the beginning
        array_unshift($logs, $log_entry);

        // Limit the number of logs
        if (count($logs) > self::MAX_LOGS) {
            $logs = array_slice($logs, 0, self::MAX_LOGS);
        }

        update_option(self::LOG_OPTION_KEY, $logs);
    }

    /**
     * Get all logs
     *
     * @param int $limit Number of logs to retrieve
     * @param string $level Filter by log level
     * @param string $action Filter by action
     * @return array
     */
    public static function get_logs($limit = null, $level = null, $action = null)
    {
        $logs = get_option(self::LOG_OPTION_KEY, []);

        if (!is_array($logs)) {
            return [];
        }

        // Filter by level
        if ($level) {
            $logs = array_filter($logs, function ($log) use ($level) {
                return isset($log['level']) && $log['level'] === $level;
            });
        }

        // Filter by action
        if ($action) {
            $logs = array_filter($logs, function ($log) use ($action) {
                return isset($log['action']) && $log['action'] === $action;
            });
        }

        // Apply limit
        if ($limit) {
            $logs = array_slice($logs, 0, $limit);
        }

        return array_values($logs);
    }

    /**
     * Clear all logs
     */
    public static function clear_logs()
    {
        delete_option(self::LOG_OPTION_KEY);
    }

    /**
     * Get client IP address
     */
    private static function get_client_ip()
    {
        $ip_keys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];

        foreach ($ip_keys as $key) {
            if (!empty($_SERVER[$key])) {
                $ip = sanitize_text_field($_SERVER[$key]);
                // Handle comma-separated IPs
                if (strpos($ip, ',') !== false) {
                    $ip = trim(explode(',', $ip)[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }

        return isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field($_SERVER['REMOTE_ADDR']) : 'unknown';
    }

    /**
     * Get log statistics
     */
    public static function get_log_stats()
    {
        $logs = get_option(self::LOG_OPTION_KEY, []);

        if (!is_array($logs)) {
            return [
                'total' => 0,
                'by_level' => [],
                'by_action' => [],
                'recent_errors' => 0
            ];
        }

        $stats = [
            'total' => count($logs),
            'by_level' => [],
            'by_action' => [],
            'recent_errors' => 0
        ];

        $one_hour_ago = strtotime('-1 hour');

        foreach ($logs as $log) {
            // Count by level
            $level = $log['level'] ?? 'unknown';
            $stats['by_level'][$level] = ($stats['by_level'][$level] ?? 0) + 1;

            // Count by action
            $action = $log['action'] ?? 'unknown';
            $stats['by_action'][$action] = ($stats['by_action'][$action] ?? 0) + 1;

            // Count recent errors
            if ($level === 'error' && isset($log['timestamp'])) {
                $log_time = strtotime($log['timestamp']);
                if ($log_time > $one_hour_ago) {
                    $stats['recent_errors']++;
                }
            }
        }

        return $stats;
    }
}
