<?php
/**
 * AuditLogAjax — AJAX handlers for the Audit Log module.
 *
 * @package UltraguardPro\modules\audit_log\ajax
 */

namespace UltraguardPro\modules\audit_log\ajax;

use UltraguardPro\Plugin;
use UltraguardPro\support\AjaxResponseBuilder;

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

// phpcs:disable WordPress.Security.NonceVerification.Missing -- Audit Log AJAX handlers are registered through the shared protected AJAX manager.

class AuditLogAjax {

    /** @var Plugin */
    private Plugin $plugin;

    public function __construct( Plugin $plugin ) {
        $this->plugin = $plugin;
    }

    public function register(): void {
        $ajax    = $this->plugin->ajax;
        $actions = [
            'ultraguard_audit_get_logs'     => [ $this, 'handle_get_logs' ],
            'ultraguard_audit_export'       => [ $this, 'handle_export' ],
            'ultraguard_audit_clear'        => [ $this, 'handle_clear' ],
            'ultraguard_audit_filter'       => [ $this, 'handle_get_logs' ],
            'ultraguard_audit_stats'        => [ $this, 'handle_stats' ],
        ];
        foreach ( $actions as $action => $cb ) {
            $ajax->register_action( $action, $cb );
        }
    }

    public function handle_get_logs(): void {
        $this->cap();
        $page        = max( 1, absint( $_POST['page'] ?? 1 ) );
        $per_page    = min( 200, max( 10, absint( $_POST['per_page'] ?? 50 ) ) );
        $action_f    = sanitize_key( wp_unslash( $_POST['filter_action']  ?? ''  ) );
        $entity_f    = sanitize_key( wp_unslash( $_POST['filter_entity']  ?? ''  ) );
        $user_f      = absint( $_POST['filter_user'] ?? 0 );

        $table = $this->t( 'audit_logs' );
        if ( ! $table ) { AjaxResponseBuilder::make()->success()->addData( 'records', [] )->addData( 'total', 0 )->send(); return; }

        $conds = [];
        if ( $action_f ) { $conds['action']      = $action_f; }
        if ( $entity_f ) { $conds['entity_type'] = $entity_f; }
        if ( $user_f   ) { $conds['user_id']     = $user_f; }

        $data = $table->paginate( $page, $per_page, $conds, 'created_at', 'DESC' );

        // Decorate with user display names
        foreach ( $data['records'] as &$r ) {
            $uid  = (int) ( $r['user_id'] ?? 0 );
            $user = $uid ? get_userdata( $uid ) : null;
            $r['user_display'] = $user ? $user->display_name . ' (#' . $uid . ')' : ( $uid ? '#' . $uid : __( 'System', 'ultraguard-security-suite' ) );
            $r['old_values']   = $r['old_values'] ? json_decode( $r['old_values'], true ) : null;
            $r['new_values']   = $r['new_values'] ? json_decode( $r['new_values'], true ) : null;
        }
        unset( $r );

        AjaxResponseBuilder::make()->success()->mergeData( (array) $data )->send();
    }

    public function handle_export(): void {
        $this->cap();
        $table = $this->t( 'audit_logs' );
        if ( ! $table ) {
            AjaxResponseBuilder::make()
                ->error( __( 'Audit log table not available.', 'ultraguard-security-suite' ) )
                ->addNotification( __( 'Audit log table not available.', 'ultraguard-security-suite' ), 'error' )
                ->send();
            return;
        }

        $rows = $table->get_by( [], 100000, 'created_at', 'DESC' );
        $url  = $this->save_export( 'audit-log-' . gmdate( 'Y-m-d-His' ) . '.csv',
            $table->export_to_csv( [], [ 'id', 'action', 'entity_type', 'entity_id', 'user_id', 'ip_address', 'old_values', 'new_values', 'created_at' ], 100000 ) );

        AjaxResponseBuilder::make()
            ->success( __( 'Audit log exported.', 'ultraguard-security-suite' ) )
            ->addData( 'download_url', $url )
            ->addData( 'count', count( $rows ) )
            ->addNotification( __( 'Audit log exported successfully.', 'ultraguard-security-suite' ), 'success' )
            ->download( $url, 'audit-log.csv' )
            ->send();
    }

    public function handle_clear(): void {
        $this->cap();
        $days  = absint( $_POST['older_than_days'] ?? 0 );
        $table = $this->t( 'audit_logs' );
        if ( ! $table ) {
            AjaxResponseBuilder::make()
                ->error( __( 'Audit log table not available.', 'ultraguard-security-suite' ) )
                ->addNotification( __( 'Audit log table not available.', 'ultraguard-security-suite' ), 'error' )
                ->send();
            return;
        }

        if ( $days > 0 ) {
            $table->delete_older_than( $days, 'created_at' );
            /* translators: %d: integer */
            $msg = sprintf( __( 'Audit log entries older than %d days cleared.', 'ultraguard-security-suite' ), $days );
        } else {
            $table->truncate();
            $msg = __( 'Entire audit log cleared.', 'ultraguard-security-suite' );
        }

        AjaxResponseBuilder::make()
            ->success( $msg )
            ->addNotification( $msg, 'success' )
            ->emptyElement( '#ultraguard-audit-log-table tbody' )
            ->updateText( '#ultraguard-audit-total-count', '0' )
            ->send();
    }

    public function handle_stats(): void {
        $this->cap();
        $table = $this->t( 'audit_logs' );
        $today = gmdate( 'Y-m-d 00:00:00' );

        $stats = [
            'total'         => $table ? $table->count() : 0,
            'today'         => $table ? $table->count( [ 'created_at >=' => $today ] ) : 0,
            'escalations'   => $table ? $table->count( [ 'action' => 'privilege_escalation' ] ) : 0,
            'login_failures'=> $table ? $table->count( [ 'action' => 'login_failed' ] ) : 0,
        ];

        AjaxResponseBuilder::make()
            ->success()
            ->mergeData( $stats )
            ->updateText( '#ultraguard-audit-stat-total',       (string) $stats['total'] )
            ->updateText( '#ultraguard-audit-stat-today',       (string) $stats['today'] )
            ->updateText( '#ultraguard-audit-stat-escalations', (string) $stats['escalations'] )
            ->updateText( '#ultraguard-audit-stat-failures',    (string) $stats['login_failures'] )
            ->send();
    }

    // ─────────────────────────────────────────────────────────────────────────

    private function cap(): void {
        if ( ! \UltraguardPro\ultraguard_current_user_can_manage() ) {
            AjaxResponseBuilder::make()->permissionError()->send( 403 );
        }
    }

    private function t( string $key ) {
        $db = $this->plugin->modules->get_db_tables();
        return $db ? $db->get_table( $key ) : null;
    }

    private function save_export( string $filename, string $content ): string {
        $upload = wp_upload_dir();
        $dir    = trailingslashit( $upload['basedir'] ) . 'ultraguard-security-suite/exports/';
        wp_mkdir_p( $dir );
        if ( ! file_exists( $dir . 'index.php' ) ) { file_put_contents( $dir . 'index.php', '<?php // silence' ); }
        file_put_contents( $dir . $filename, $content );
        return trailingslashit( $upload['baseurl'] ) . 'ultraguard-security-suite/exports/' . $filename;
    }
}

// phpcs:enable
