<?php

if (!defined('ABSPATH')) {
    exit;
}

class BS2FA_Logger {
    public static function add($event, $context = [], $level = 'info') {
        $logs = get_option('bs2fa_logs', []);
        if (!is_array($logs)) {
            $logs = [];
        }

        $entry = [
            'time'     => time(),
            'event'    => sanitize_key($event),
            'level'    => sanitize_key($level),
            'user_id'  => isset($context['user_id']) ? (int) $context['user_id'] : 0,
            'username' => isset($context['username']) ? sanitize_user((string) $context['username'], true) : '',
            'ip'       => BS2FA_Helpers::client_ip(),
            'details'  => isset($context['details']) ? sanitize_textarea_field((string) $context['details']) : '',
        ];

        array_unshift($logs, $entry);
        $limit = max(50, (int) BS2FA_Helpers::get_option('log_retention_items', 300));
        if (count($logs) > $limit) {
            $logs = array_slice($logs, 0, $limit);
        }

        update_option('bs2fa_logs', $logs, false);
    }

    protected static function normalize_filters($args = []) {
        return [
            'user_id' => isset($args['user_id']) ? (int) $args['user_id'] : 0,
            'limit'   => isset($args['limit']) ? max(1, (int) $args['limit']) : 30,
            'offset'  => isset($args['offset']) ? max(0, (int) $args['offset']) : 0,
            'level'   => isset($args['level']) ? sanitize_key($args['level']) : '',
            'event'   => isset($args['event']) ? sanitize_key($args['event']) : '',
            'ip'      => isset($args['ip']) ? sanitize_text_field($args['ip']) : '',
            'search'  => isset($args['search']) ? sanitize_text_field($args['search']) : '',
        ];
    }

    protected static function matches($entry, $filters) {
        if (!empty($filters['user_id']) && (int) ($entry['user_id'] ?? 0) !== (int) $filters['user_id']) {
            return false;
        }

        if (!empty($filters['level']) && sanitize_key((string) ($entry['level'] ?? '')) !== $filters['level']) {
            return false;
        }

        if (!empty($filters['event']) && sanitize_key((string) ($entry['event'] ?? '')) !== $filters['event']) {
            return false;
        }

        if (!empty($filters['ip']) && stripos((string) ($entry['ip'] ?? ''), $filters['ip']) === false) {
            return false;
        }

        if (!empty($filters['search'])) {
            $haystack = implode(' ', [
                (string) ($entry['event'] ?? ''),
                (string) ($entry['details'] ?? ''),
                (string) ($entry['username'] ?? ''),
                (string) ($entry['ip'] ?? ''),
                (string) ($entry['user_id'] ?? ''),
            ]);
            if (stripos($haystack, $filters['search']) === false) {
                return false;
            }
        }

        return true;
    }

    protected static function filtered($args = []) {
        $logs = get_option('bs2fa_logs', []);
        $logs = is_array($logs) ? $logs : [];
        $filters = self::normalize_filters($args);

        if ($filters['user_id'] || $filters['level'] || $filters['event'] || $filters['ip'] || $filters['search']) {
            $logs = array_values(array_filter($logs, function ($entry) use ($filters) {
                return self::matches($entry, $filters);
            }));
        }

        return [$logs, $filters];
    }

    public static function get_logs($args = []) {
        [$logs, $filters] = self::filtered($args);
        return array_slice($logs, $filters['offset'], $filters['limit']);
    }

    public static function count_logs($args = []) {
        [$logs] = self::filtered($args);
        return count($logs);
    }

    public static function distinct_events() {
        $events = [];
        foreach (self::all() as $log) {
            $event = sanitize_key((string) ($log['event'] ?? ''));
            if ($event !== '') {
                $events[$event] = true;
            }
        }
        $events = array_keys($events);
        sort($events);
        return $events;
    }

    public static function all() {
        $logs = get_option('bs2fa_logs', []);
        return is_array($logs) ? $logs : [];
    }

    public static function clear() {
        delete_option('bs2fa_logs');
    }
}
