<?php

declare(strict_types=1);

namespace SecurWP\Modules\Scanner\Service;

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

use SecurWP\Modules\Scanner\Service\ScanLogger;

/**
 * Centralized handler for critical scan failures.
 * Triggers alerts for admin notifications and frontend modals.
 */
class ScanAlertService {

    /**
     * Build a safe alert payload for frontend consumption.
     *
     * @param string $type
     * @param string $message
     * @param array  $context
     * @return array<string,mixed>
     */
    private static function build_alert_payload( string $type, string $message, array $context ): array {
        $payload = [
            'type'       => sanitize_key( $type ),
            'message'    => sanitize_text_field( $message ),
            'timestamp'  => time(),
            'scan_id'    => isset( $context['scan_id'] ) ? sanitize_text_field( (string) $context['scan_id'] ) : '',
            'error_code' => isset( $context['error_code'] ) ? sanitize_key( (string) $context['error_code'] ) : '',
            'stage'      => isset( $context['stage'] ) ? sanitize_key( (string) $context['stage'] ) : '',
            'incident_ref' => isset( $context['incident_ref'] ) ? sanitize_text_field( (string) $context['incident_ref'] ) : '',
            'request_id' => isset( $context['request_id'] ) ? sanitize_text_field( (string) $context['request_id'] ) : '',
            'status_code' => isset( $context['status_code'] ) ? (int) $context['status_code'] : 0,
            'retryable'  => array_key_exists( 'retryable', $context ) ? (bool) $context['retryable'] : true,
            'context'    => $context,
        ];

        if ( isset( $context['technical_message'] ) ) {
            $payload['technical_message'] = sanitize_text_field( (string) $context['technical_message'] );
        }

        return $payload;
    }

    /**
     * Send a critical scan failure alert.
     *
     * @param string $type    Alert type (e.g., 'system_error', 'timeout').
     * @param string $message User-facing error message.
     * @param array  $context Additional debug context.
     * @return void
     */
    public static function send_alert( string $type, string $message, array $context = [] ) {
        securwp_log( sprintf(
            '[SecurWP] KEY SCAN FAILURE: [%s] %s. Context: %s',
            strtoupper( $type ),
            $message,
            json_encode( $context )
        ) );

        if ( class_exists( ScanLogger::class ) ) {
            ScanLogger::log( $message, 3, 'error' );
        }

        do_action( 'securwp_scan_failure_alert', $type, $message, $context );

        // The primary failure communication is via ScanQueue status='failed'.
        // This transient is for out-of-band alerts if the DB is unreadable.
        set_transient( 'securwp_last_scan_alert', self::build_alert_payload( $type, $message, $context ), 300 );
    }
}
