<?php

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

final class AISBW_Logger
{
    private wpdb $wpdb;
    private string $table;

    public function __construct()
    {
        global $wpdb;

        $this->wpdb = $wpdb;
        $this->table = $wpdb->prefix . 'aisbw_logs';
    }

    public function info(string $action, string $message = '', array $context = [], ?int $topic_id = null): void
    {
        $this->log('info', $action, $message, $context, $topic_id);
    }

    public function warning(string $action, string $message = '', array $context = [], ?int $topic_id = null): void
    {
        $this->log('warning', $action, $message, $context, $topic_id);
    }

    public function error(string $action, string $message = '', array $context = [], ?int $topic_id = null): void
    {
        $this->log('error', $action, $message, $context, $topic_id);
    }

    public function log(string $level, string $action, string $message = '', array $context = [], ?int $topic_id = null): void
    {
        $context = $this->redact_sensitive_context($context);

        $this->wpdb->insert(
            $this->table,
            [
                'topic_id' => $topic_id ?: null,
                'level' => sanitize_key($level),
                'action' => sanitize_key($action),
                'message' => sanitize_textarea_field($message),
                'context' => $context ? wp_json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : null,
                'created_at' => current_time('mysql'),
            ],
            ['%d', '%s', '%s', '%s', '%s', '%s']
        );
    }

    public function all(int $limit = 200): array
    {
        $limit = max(1, min(500, $limit));

        return $this->wpdb->get_results(
            $this->wpdb->prepare("SELECT * FROM {$this->table} ORDER BY created_at DESC LIMIT %d", $limit),
            ARRAY_A
        ) ?: [];
    }

    public function count_today(array|string $actions = []): int
    {
        $start = date('Y-m-d 00:00:00', current_time('timestamp'));
        $actions = is_array($actions) ? $actions : [$actions];
        $actions = array_values(array_filter(array_map('sanitize_key', $actions)));

        if (!$actions) {
            return (int) $this->wpdb->get_var(
                $this->wpdb->prepare("SELECT COUNT(*) FROM {$this->table} WHERE created_at >= %s", $start)
            );
        }

        $placeholders = implode(',', array_fill(0, count($actions), '%s'));
        $params = array_merge($actions, [$start]);

        return (int) $this->wpdb->get_var(
            $this->wpdb->prepare("SELECT COUNT(*) FROM {$this->table} WHERE action IN ({$placeholders}) AND created_at >= %s", $params)
        );
    }

    private function redact_sensitive_context(array $context): array
    {
        foreach ($context as $key => $value) {
            $normalized = strtolower((string) $key);

            if (str_contains($normalized, 'key') || str_contains($normalized, 'token') || str_contains($normalized, 'secret')) {
                $context[$key] = '[redacted]';
            } elseif (is_array($value)) {
                $context[$key] = $this->redact_sensitive_context($value);
            }
        }

        return $context;
    }
}
