<?php
/**
 * VmpFence Audit Log Sync Module
 *
 * Syncs records from wp_vmpfence_audit_log to the backend
 * via POST /api/v1/logging/audit-logs/batch (payload key: 'logs')
 *
 * @package    VMPFence
 * @subpackage Includes\Sync
 * @since      2.2.4
 */

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

class VmpFence_Audit_Log_Sync extends VmpFence_Base_Sync {

    /**
     * Records per API call
     * @var int
     */
    protected $batch_size = 50;

    /**
     * Constructor
     *
     * @since 2.2.4
     */
    public function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'vmpfence_audit_log';
        parent::__construct();
    }

    /**
     * Get the API client method name for this sync module.
     *
     * @since 2.2.4
     * @return string
     */
    protected function get_endpoint_method(): string {
        return 'sync_audit_logs_batch';
    }

    /**
     * Transform a database row into the API payload format.
     *
     * DB Audit (Feb 16, 2026):
     * - Backend field is `wp_user_id`, NOT `user_id`
     * - Backend field is `wp_username`, NOT `username`
     * - Backend field is `occurred_at`, NOT `created_at`
     * - `wp_user_role` and `severity` are NOT NULL on server — always sent
     * - `ip_address` is stored as varbinary(16) — converted via format_ip()
     * - `time` is double(17,6) Unix timestamp — converted via date()
     *
     * Column Audit (Feb 15, 2026 — Bugfix):
     * - No `severity` column in audit_log table — derive from event_type/action
     *
     * @since 2.2.4
     * @param array $row Database row
     * @return array Transformed record
     */
    protected function transform_record(array $row): array {
        return array(
            'plugin_event_id' => (int) $row['id'],
            'action_type'     => $row['event_type'] ?? '',
            'wp_user_id'      => (int) ($row['user_id'] ?? 0),
            'wp_username'     => $row['username'] ?? '',
            'wp_user_role'    => $row['user_role'] ?? 'subscriber',
            'description'     => $row['message'] ?? '',
            'ip_address'      => isset($row['source_ip']) ? $this->format_ip($row['source_ip']) : null,
            'user_agent'      => ! empty($row['user_agent']) ? $row['user_agent'] : null,
            'object_type'     => ! empty($row['object_type']) ? $row['object_type'] : null,
            'object_id'       => ! empty($row['object_id']) ? (int) $row['object_id'] : null,
            'object_name'     => ! empty($row['object_name']) ? $row['object_name'] : null,
            'old_value'       => ! empty($row['old_value']) ? $row['old_value'] : null,
            'new_value'       => ! empty($row['new_value']) ? $row['new_value'] : null,
            'severity'        => self::derive_severity($row),
            'occurred_at'     => isset($row['time']) ? gmdate('Y-m-d\TH:i:s\Z', (int) $row['time']) : current_time('c'),
        );
    }

    /**
     * Derive severity from event_type and action since audit_log table has no severity column.
     *
     * @since 2.2.4
     * @param array $row Database row
     * @return string Severity level (critical, high, medium, low, info)
     */
    private static function derive_severity(array $row): string {
        $event_type = strtolower($row['event_type'] ?? '');
        $action = strtolower($row['action'] ?? '');

        // Critical: user deletions, role changes to admin, plugin/theme file edits
        if (strpos($event_type, 'delete') !== false && strpos($event_type, 'user') !== false) return 'critical';
        if ($action === 'role_change' && strpos(strtolower($row['new_value'] ?? ''), 'admin') !== false) return 'critical';

        // High: login failures, permission changes, file modifications
        if (strpos($event_type, 'login_fail') !== false) return 'high';
        if (strpos($event_type, 'permission') !== false || strpos($action, 'capability') !== false) return 'high';

        // Medium: settings changes, user edits
        if (strpos($event_type, 'setting') !== false || strpos($event_type, 'option') !== false) return 'medium';
        if (strpos($action, 'update') !== false || strpos($action, 'edit') !== false) return 'medium';

        // Low: logins, logouts, views
        if (strpos($event_type, 'login') !== false || strpos($event_type, 'logout') !== false) return 'low';

        return 'info';
    }
}
