<?php

declare(strict_types=1);

/**
 * IssueDisplayContractBuilder - Enrichment and UI Contract Building
 *
 * Extracted from IssueRepository to isolate enrichment logic from persistence.
 * Builds the display DTO and action policy that the frontend consumes as the
 * authoritative source of truth for card copy and available actions.
 *
 */

namespace SiteFort\Modules\Scanner\Repository;

use SiteFort\Includes\Capabilities;
use SiteFort\Includes\SitePathResolver;
use SiteFort\Modules\Scanner\Service\IssueType;
use SiteFort\Modules\Scanner\Service\MalwareFindingFormatter;

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

class IssueDisplayContractBuilder {
    private const REPAIR_UPGRADE_MESSAGE = 'Upgrade to Pro for one-click repair from a verified clean copy.';
    private const REPAIR_UPGRADE_URL     = 'https://securewp.net/pricing/#plan';

    /**
     * WordPress-managed files that live at the install root and should be
     * treated as core-owned assets for display/action policy decisions.
     */
    private const KNOWN_ROOT_CORE_FILES = [
        'index.php',
        'license.txt',
        'readme.html',
        'wp-activate.php',
        'wp-blog-header.php',
        'wp-comments-post.php',
        'wp-config-sample.php',
        'wp-config.php',
        'wp-cron.php',
        'wp-links-opml.php',
        'wp-load.php',
        'wp-login.php',
        'wp-mail.php',
        'wp-settings.php',
        'wp-signup.php',
        'wp-trackback.php',
        'xmlrpc.php',
    ];

    private static function normalize_row_data( array $row ): array {
        if ( isset( $row['data'] ) && is_array( $row['data'] ) ) {
            return $row['data'];
        }

        if ( isset( $row['data'] ) && is_string( $row['data'] ) && $row['data'] !== '' ) {
            $decoded = json_decode( $row['data'], true );
            if ( is_array( $decoded ) ) {
                return $decoded;
            }
        }

        return [];
    }

    private static function normalize_relative_file_path( string $file_path ): string {
        $normalized = ltrim( wp_normalize_path( $file_path ), '/' );
        $root       = ltrim( wp_normalize_path( trailingslashit( ABSPATH ) ), '/' );

        if ( $root !== '' && strpos( $normalized, $root ) === 0 ) {
            $normalized = ltrim( substr( $normalized, strlen( $root ) ), '/' );
        }

        return $normalized;
    }

    private static function get_server_config_relative_files(): array {
        $files = [ '.htaccess', '.user.ini' ];
        $user_ini_filename = SitePathResolver::get_user_ini_filename();
        if ( $user_ini_filename !== '' ) {
            $files[] = $user_ini_filename;
        }

        return array_values( array_unique( $files ) );
    }

    private static function is_root_level_file( string $relative_path ): bool {
        return $relative_path !== '' && strpos( $relative_path, '/' ) === false;
    }

    private static function is_known_root_core_file( string $relative_path ): bool {
        return self::is_root_level_file( $relative_path )
            && in_array( strtolower( $relative_path ), self::KNOWN_ROOT_CORE_FILES, true );
    }

    private static function is_root_core_integrity_finding( array $row, string $relative_path ): bool {
        if ( ! self::is_root_level_file( $relative_path ) ) {
            return false;
        }

        $data           = self::normalize_row_data( $row );
        $detection_type = sanitize_key( (string) ( $data['detection_type'] ?? '' ) );
        $policy_reason  = sanitize_key( (string) ( $data['policy_reason'] ?? '' ) );

        return in_array( $detection_type, [ 'core_unknown_file', 'core_legacy_file' ], true )
            || in_array( $policy_reason, [ 'unknown_core_system_file', 'legacy_core_system_file' ], true );
    }

    private static function can_edit_user_remediation_target( int $user_id ): bool {
        return Capabilities::can_edit_user_account( $user_id );
    }

    private static function can_delete_user_remediation_target( int $user_id ): bool {
        if ( $user_id <= 0 || $user_id === get_current_user_id() ) {
            return false;
        }

        return Capabilities::can_delete_user_account( $user_id );
    }

    private static function resolve_authorized_content_edit_url( array $data ): string {
        $edit_url = trim( (string) ( $data['edit_url'] ?? '' ) );
        if ( $edit_url === '' || ! function_exists( 'current_user_can' ) ) {
            return '';
        }

        $table = sanitize_key( (string) ( $data['table'] ?? '' ) );

        switch ( $table ) {
            case 'posts':
            case 'postmeta':
                $post_id = isset( $data['post_id'] ) ? (int) $data['post_id'] : 0;
                return $post_id > 0 && current_user_can( 'edit_post', $post_id ) ? $edit_url : '';

            case 'comments':
                $comment_id = isset( $data['comment_id'] ) ? (int) $data['comment_id'] : 0;
                return $comment_id > 0 && current_user_can( 'edit_comment', $comment_id ) ? $edit_url : '';

            case 'usermeta':
                $user_id = isset( $data['user_id'] ) ? (int) $data['user_id'] : 0;
                return $user_id > 0 && self::can_edit_user_remediation_target( $user_id ) ? $edit_url : '';

            default:
                return $edit_url;
        }
    }

    private static function apply_authorized_admin_urls( array $row ): array {
        if ( ! isset( $row['data'] ) || ! is_array( $row['data'] ) ) {
            return $row;
        }

        $category = self::normalize_issue_category( (string) ( $row['type'] ?? '' ) );

        if ( $category === 'content' ) {
            $authorized_edit_url = self::resolve_authorized_content_edit_url( $row['data'] );
            if ( $authorized_edit_url !== '' ) {
                $row['data']['edit_url'] = $authorized_edit_url;
            } else {
                unset( $row['data']['edit_url'] );
            }

            return $row;
        }

        if ( $category === 'user' ) {
            $user_id = isset( $row['data']['user_id'] ) ? (int) $row['data']['user_id'] : 0;
            if ( $user_id > 0 && self::can_edit_user_remediation_target( $user_id ) ) {
                $row['data']['edit_url'] = admin_url( "user-edit.php?user_id={$user_id}" );
                $row['data']['password_edit_url'] = admin_url( "user-edit.php?user_id={$user_id}#password" );
            } else {
                unset( $row['data']['edit_url'], $row['data']['password_edit_url'] );
            }
        }

        return $row;
    }

    private static function resolve_component_context_value( string $component_type, string $file_path ): string {
        $relative_path = self::normalize_relative_file_path( $file_path );

        if ( $relative_path === 'wp-config.php' ) {
            return 'WordPress Configuration';
        }

        if ( in_array( $relative_path, self::get_server_config_relative_files(), true ) ) {
            return 'Server Configuration';
        }

        switch ( $component_type ) {
            case 'plugin':
                return 'Plugin';
            case 'theme':
                return 'Theme';
            case 'core':
                return 'Core';
            case 'uploads':
                return 'Uploads';
            default:
                return 'Unknown';
        }
    }

    private static function resolve_component_asset_name( string $component_type, string $component_slug, array $data = [] ): string {
        static $plugin_name_map = null;
        static $theme_name_map = null;

        $asset_name = trim( (string) ( $data['component_name'] ?? ( $data['asset_name'] ?? '' ) ) );
        if ( $asset_name !== '' ) {
            return $asset_name;
        }

        $component_slug = sanitize_key( $component_slug );
        if ( $component_type === 'core' ) {
            return 'WordPress Core';
        }

        if ( $component_type === 'plugin' && $component_slug !== '' ) {
            if ( $plugin_name_map === null ) {
                $plugin_name_map = [];
                if ( ! function_exists( 'get_plugins' ) && defined( 'ABSPATH' ) ) {
                    require_once ABSPATH . 'wp-admin/includes/plugin.php';
                }
                if ( function_exists( 'get_plugins' ) ) {
                    foreach ( get_plugins() as $plugin_file => $plugin_data ) {
                        $slug = dirname( (string) $plugin_file );
                        if ( $slug === '.' || $slug === '' ) {
                            $slug = basename( (string) $plugin_file, '.php' );
                        }
                        if ( ! isset( $plugin_name_map[ $slug ] ) && ! empty( $plugin_data['Name'] ) ) {
                            $plugin_name_map[ $slug ] = (string) $plugin_data['Name'];
                        }
                    }
                }
            }
            if ( isset( $plugin_name_map[ $component_slug ] ) ) {
                return $plugin_name_map[ $component_slug ];
            }
        }

        if ( $component_type === 'theme' && $component_slug !== '' ) {
            if ( $theme_name_map === null ) {
                $theme_name_map = [];
                if ( function_exists( 'wp_get_themes' ) ) {
                    foreach ( wp_get_themes() as $theme_slug => $theme_obj ) {
                        if ( $theme_obj instanceof \WP_Theme ) {
                            $theme_name = trim( (string) $theme_obj->get( 'Name' ) );
                            if ( $theme_name !== '' ) {
                                $theme_name_map[ (string) $theme_slug ] = $theme_name;
                            }
                        }
                    }
                }
            }
            if ( isset( $theme_name_map[ $component_slug ] ) ) {
                return $theme_name_map[ $component_slug ];
            }
        }

        return '';
    }

    private static function build_integrity_display_description( string $component_type, string $asset_name, string $version, string $fallback_description ): string {
        $version_clause = $version !== '' ? sprintf( ' for the installed version (%s)', $version ) : '';

        if ( $component_type === 'plugin' ) {
            $subject = $asset_name !== '' ? sprintf( 'the official %s plugin files', $asset_name ) : 'the official plugin files';
            return sprintf(
                'This file differs from %s%s. This can result from an approved customization, an incomplete update, or unauthorized tampering. Validate the recent change history and compare the file with a verified clean copy before marking it safe.',
                $subject,
                $version_clause
            );
        }

        if ( $component_type === 'theme' ) {
            $subject = $asset_name !== '' ? sprintf( 'the official %s theme files', $asset_name ) : 'the official theme files';
            return sprintf(
                'This file differs from %s%s. This can result from an approved customization, an incomplete update, or unauthorized tampering. Validate the recent change history and compare the file with a verified clean copy before marking it safe.',
                $subject,
                $version_clause
            );
        }

        if ( $component_type === 'core' ) {
            return sprintf(
                'This file differs from the official WordPress core files%s. Core file changes should be treated as high risk because they can affect platform integrity, update reliability, and incident response. Validate the recent change history and compare the file with a verified clean copy before marking it safe.',
                $version_clause
            );
        }

        return $fallback_description;
    }

    private static function is_checksum_mismatch_integrity_issue( array $row, array $data ): bool {
        $detection_type = sanitize_key( (string) ( $data['detection_type'] ?? '' ) );
        if ( $detection_type === 'checksum_mismatch' ) {
            return true;
        }

        if ( in_array( $detection_type, [ 'core_unknown_file', 'core_legacy_file', 'plugin_orphaned_file' ], true ) ) {
            return false;
        }

        $policy_reason = sanitize_key( (string) ( $data['policy_reason'] ?? '' ) );
        if ( in_array( $policy_reason, [ 'unknown_core_system_file', 'legacy_core_system_file', 'unknown_plugin_file' ], true ) ) {
            return false;
        }

        $status = sanitize_key( (string) ( $row['status'] ?? '' ) );
        if ( in_array( $status, [ 'unknown', 'missing' ], true ) ) {
            return false;
        }

        $description = strtolower( trim( (string) ( $row['details'] ?? $data['description'] ?? '' ) ) );
        if ( $description !== '' && str_contains( $description, 'intel integrity baseline' ) ) {
            return true;
        }

        $title = strtolower( trim( (string) ( $row['title'] ?? $data['title'] ?? '' ) ) );
        if ( str_starts_with( $title, 'modified ' ) && str_contains( $title, ' file detected' ) ) {
            return true;
        }

        $message = strtolower( trim( (string) ( $row['message'] ?? '' ) ) );
        return str_contains( $message, 'file modified:' );
    }

    private static function allowsRepair(): bool {
        if ( ! class_exists( '\SiteFort\Modules\Cloud\Service\Entitlements' ) ) {
            $path = dirname( dirname( __DIR__ ) ) . '/Cloud/Service/Entitlements.php';
            if ( file_exists( $path ) ) {
                require_once $path;
            }
        }

        return class_exists( '\SiteFort\Modules\Cloud\Service\Entitlements' )
            && \SiteFort\Modules\Cloud\Service\Entitlements::allowsRepair();
    }

    private static function is_core_integrity_delete_candidate( string $category, string $component_type, string $status, string $detection_type, string $policy_reason ): bool {
        if ( $category !== 'integrity' || $component_type !== 'core' ) {
            return false;
        }

        if ( $status === 'unknown' ) {
            return true;
        }

        if ( in_array( $detection_type, [ 'core_unknown_file', 'core_legacy_file' ], true ) ) {
            return true;
        }

        return in_array( $policy_reason, [ 'unknown_core_system_file', 'legacy_core_system_file' ], true );
    }

    private static function is_plugin_integrity_delete_candidate( string $category, string $component_type, string $detection_type, string $policy_reason ): bool {
        if ( $category !== 'integrity' || $component_type !== 'plugin' ) {
            return false;
        }

        if ( $detection_type === 'plugin_orphaned_file' ) {
            return true;
        }

        return $policy_reason === 'unknown_plugin_file';
    }

    private static function is_nonbaseline_integrity_file( string $category, string $component_type, string $status, string $detection_type, string $policy_reason ): bool {
        return self::is_core_integrity_delete_candidate( $category, $component_type, $status, $detection_type, $policy_reason )
            || self::is_plugin_integrity_delete_candidate( $category, $component_type, $detection_type, $policy_reason );
    }

    /**
     * Malware delete requires quarantine only when delete is the fallback for a
     * core-owned file whose clean baseline could not be resolved by IntelEngine.
     *
     * @param array $row Issue row.
     * @return bool
     */
    public static function requires_delete_quarantine( array $row ): bool {
        $data = self::normalize_row_data( $row );
        $row['data'] = $data;

        if ( self::normalize_issue_category( (string) ( $row['type'] ?? '' ) ) !== 'malware' ) {
            return false;
        }

        if ( array_key_exists( 'repair_available', $data ) && wp_validate_boolean( $data['repair_available'] ) ) {
            return false;
        }

        $file_path = (string) ( $row['file'] ?? $row['file_path'] ?? '' );
        if ( $file_path === '' || self::get_file_protection_tier( $file_path ) !== null ) {
            return false;
        }

        if ( self::infer_component_type( $row ) !== 'core' ) {
            return false;
        }

        return self::has_unresolved_core_baseline( $data );
    }

    private static function has_unresolved_core_baseline( array $data ): bool {
        $hash_status = sanitize_key( (string) ( $data['hash_status'] ?? $data['hash_verdict'] ?? $data['hash_check_status'] ?? '' ) );
        if ( in_array( $hash_status, [ 'unknown', 'safe_stale', 'unindexed', 'not_indexed', 'missing_baseline', 'unresolved' ], true ) ) {
            return true;
        }

        $baseline_status = sanitize_key( (string) ( $data['baseline_status'] ?? $data['core_baseline_status'] ?? '' ) );
        if ( in_array( $baseline_status, [ 'unknown', 'unindexed', 'not_indexed', 'missing', 'unresolved' ], true ) ) {
            return true;
        }

        $detection_type = sanitize_key( (string) ( $data['detection_type'] ?? '' ) );
        if ( in_array( $detection_type, [ 'core_unknown_file', 'deep_scan_unknown_core', 'unknown_core_malware' ], true ) ) {
            return true;
        }

        $policy_reason = sanitize_key( (string) ( $data['policy_reason'] ?? '' ) );
        if ( in_array( $policy_reason, [ 'unknown_core_system_file', 'core_version_unindexed', 'unindexed_core_version', 'missing_core_baseline' ], true ) ) {
            return true;
        }

        $core_origin = sanitize_key( (string) ( $data['core_origin'] ?? $data['origin'] ?? '' ) );
        return $core_origin === 'unknown';
    }

    public static function allows_delete_action( array $row ): bool {
        $data = self::normalize_row_data( $row );
        $row['data'] = $data;

        $issue_type = sanitize_key( (string) ( $row['type'] ?? '' ) );
        $category = self::normalize_issue_category( (string) ( $row['type'] ?? '' ) );
        $component_type = self::infer_component_type( $row );
        $file_path = (string) ( $row['file'] ?? $row['file_path'] ?? '' );
        $status = sanitize_key( (string) ( $row['status'] ?? '' ) );
        $detection_type = sanitize_key( (string) ( $data['detection_type'] ?? '' ) );
        $policy_reason = sanitize_key( (string) ( $data['policy_reason'] ?? '' ) );

        if ( $file_path === '' ) {
            return false;
        }

        // A file too large to scan is never a legitimate core file, so allow deleting it wherever it lives.
        if ( $issue_type === IssueType::SKIPPED && ( $status === 'too_large' || ( $data['reason'] ?? '' ) === 'file_too_large' ) ) {
            return true;
        }

        if ( $issue_type === IssueType::FAKE_IMAGE || $detection_type === 'image_type_mismatch' ) {
            return $component_type !== 'core';
        }

        if ( $category === 'malware' ) {
            if ( array_key_exists( 'repair_available', $data ) && wp_validate_boolean( $data['repair_available'] ) ) {
                return false;
            }

            return true;
        }

        if ( $category === 'integrity' ) {
            return self::is_nonbaseline_integrity_file( $category, $component_type, $status, $detection_type, $policy_reason );
        }

        return $component_type !== 'core'
            || self::is_core_integrity_delete_candidate( $category, $component_type, $status, $detection_type, $policy_reason );
    }

    /**
     * Convert an internal issue status to a user-facing subtitle when appropriate.
     *
     * Workflow states like "open" and "resolved" describe repository state, not
     * the finding itself, so they should never leak into the card header.
     */
    private static function resolve_status_subtitle( string $status ): string {
        $status = trim( $status );
        if ( $status === '' ) {
            return '';
        }

        $normalized = sanitize_key( $status );
        if ( in_array( $normalized, [ 'open', 'resolved' ], true ) ) {
            return '';
        }

        return $status;
    }

    private static function resolve_fake_image_validation_label( array $data ): string {
        $reason = sanitize_key( (string) ( $data['validation_reason'] ?? '' ) );
        switch ( $reason ) {
            case 'non_image_payload':
                return 'Non-image content detected (PHP/HTML/text)';
            case 'non_image_mime':
                return 'File detected as executable or text content';
            case 'embedded_code_payload':
                return 'Executable or HTML content detected inside the image';
            case 'extension_magic_mismatch':
                return 'File extension does not match file signature';
            case 'extension_parser_mismatch':
                return 'File extension does not match parsed image format';
            case 'extension_mime_mismatch':
                return 'File extension does not match detected content type';
            case 'missing_image_magic':
                return 'Image header not found';
            case 'image_parser_failed':
                return 'Image could not be parsed';
            case 'missing_svg_root':
                return 'SVG root element not found';
            case 'svg_active_content':
                return 'SVG contains active content (script/event handlers)';
            case 'unreadable_image':
                return 'File could not be read';
            case 'empty_image':
                return 'File is empty';
            default:
                break;
        }

        $expected = sanitize_key( (string) ( $data['expected_extension'] ?? '' ) );
        $detected = sanitize_key( (string) ( $data['detected_type'] ?? '' ) );
        if ( $expected !== '' && $detected !== '' ) {
            return sprintf( 'Expected %s, found %s', strtoupper( $expected ), strtoupper( $detected ) );
        }

        return 'Image content validation failed';
    }

    private static function supports_reference_diff( array $row, array $data, string $category, string $component_type ): bool {
        if ( $category === 'integrity' ) {
            return self::is_checksum_mismatch_integrity_issue( $row, $data );
        }

        if ( $category !== 'malware' ) {
            return false;
        }

        if ( ! in_array( $component_type, [ 'core', 'plugin', 'theme' ], true ) ) {
            return false;
        }

        $expected_hash = trim( (string) ( $data['expected_hash'] ?? '' ) );
        if ( $expected_hash !== '' ) {
            return true;
        }

        if ( array_key_exists( 'repair_available', $data ) && wp_validate_boolean( $data['repair_available'] ) ) {
            return true;
        }

        $hash_status = sanitize_key( (string) ( $data['hash_status'] ?? $data['hash_verdict'] ?? '' ) );
        return $hash_status === 'modified';
    }

    /**
     * Full enrichment pipeline: JSON decode, field normalization, display contract, action policy.
     * Drop-in replacement for IssueRepository::enrichIssue().
     *
     * @param array $row Raw DB row
     * @return array Enriched issue
     */
    public static function enrich( array $row ): array {
        static $plugin_name_map = null;
        static $theme_name_map = null;

        if ( ! empty( $row['data'] ) ) {
            $row['data'] = json_decode( $row['data'], true );
        }
        if ( ! isset( $row['data'] ) || ! is_array( $row['data'] ) ) {
            $row['data'] = [];
        }

        $row = self::apply_authorized_admin_urls( $row );

        $row['hash'] = $row['issue_hash'];
        $row['file'] = $row['file_path'];
        $row['id']   = $row['issue_hash']; // Use hash as ID for frontend
        $row['is_ignored'] = (bool) $row['is_ignored'];

        // Restore Slug from Data (if persisted)
        if ( isset( $row['data']['slug'] ) ) {
            $row['slug'] = $row['data']['slug'];
        }

        // Enrich vulnerability display name for current and legacy rows.
        // Prevents slug-only titles in UI when older records did not persist asset names.
        if ( isset( $row['type'] ) && 'vulnerability' === $row['type'] ) {
            $component_type = sanitize_key( (string) ( $row['data']['component_type'] ?? 'plugin' ) );
            $asset_slug = sanitize_key( (string) ( $row['data']['slug'] ?? ( $row['slug'] ?? '' ) ) );
            $asset_name = trim( (string) ( $row['data']['component_name'] ?? ( $row['data']['asset_name'] ?? '' ) ) );

            if ( $asset_name === '' ) {
                if ( 'plugin' === $component_type && $asset_slug !== '' ) {
                    if ( $plugin_name_map === null ) {
                        $plugin_name_map = [];
                        if ( ! function_exists( 'get_plugins' ) && defined( 'ABSPATH' ) ) {
                            require_once ABSPATH . 'wp-admin/includes/plugin.php';
                        }
                        if ( function_exists( 'get_plugins' ) ) {
                            $installed_plugins = get_plugins();
                            foreach ( $installed_plugins as $plugin_file => $plugin_data ) {
                                $slug = dirname( $plugin_file );
                                if ( $slug === '.' || $slug === '' ) {
                                    $slug = basename( $plugin_file, '.php' );
                                }
                                if ( ! isset( $plugin_name_map[ $slug ] ) && ! empty( $plugin_data['Name'] ) ) {
                                    $plugin_name_map[ $slug ] = (string) $plugin_data['Name'];
                                }
                            }
                        }
                    }
                    if ( isset( $plugin_name_map[ $asset_slug ] ) ) {
                        $asset_name = $plugin_name_map[ $asset_slug ];
                    }
                } elseif ( 'theme' === $component_type && $asset_slug !== '' ) {
                    if ( $theme_name_map === null ) {
                        $theme_name_map = [];
                        if ( function_exists( 'wp_get_themes' ) ) {
                            $themes = wp_get_themes();
                            foreach ( $themes as $theme_slug => $theme_obj ) {
                                if ( $theme_obj instanceof \WP_Theme ) {
                                    $theme_name = trim( (string) $theme_obj->get( 'Name' ) );
                                    if ( $theme_name !== '' ) {
                                        $theme_name_map[ (string) $theme_slug ] = $theme_name;
                                    }
                                }
                            }
                        }
                    }
                    if ( isset( $theme_name_map[ $asset_slug ] ) ) {
                        $asset_name = $theme_name_map[ $asset_slug ];
                    }
                } elseif ( 'core' === $component_type ) {
                    $asset_name = 'WordPress Core';
                }
            }

            if ( $asset_name !== '' ) {
                $row['data']['component_name'] = $asset_name;
                $row['data']['asset_name'] = $asset_name;
            }
        }

        // Restore can_update (frontend requirement)
        if ( isset( $row['data']['can_update'] ) ) {
            $row['can_update'] = (bool) $row['data']['can_update'];
        }

        // Malware findings are treated as critical across all detection paths.
        if ( isset( $row['type'] ) && 'malware' === $row['type'] ) {
            $row['severity'] = 'critical';
            $malware_payload = $row['data'];
            if ( empty( $malware_payload['threat_type'] ) && ! empty( $row['threat_type'] ) ) {
                $malware_payload['threat_type'] = (string) $row['threat_type'];
            }
            if ( empty( $malware_payload['threat_type'] ) && ! empty( $row['title'] ) && stripos( (string) $row['title'], 'Malware Detected:' ) === 0 ) {
                $malware_payload['threat_type'] = trim( substr( (string) $row['title'], strlen( 'Malware Detected:' ) ) );
            }
            $normalized_threat = MalwareFindingFormatter::resolveThreatLabel( $malware_payload );
            $normalized_description = MalwareFindingFormatter::buildDescription(
                $malware_payload,
                (string) ( $row['file_path'] ?? '' )
            );
            $row['threat_type'] = $normalized_threat;
            $row['data']['threat_type'] = $normalized_threat;
            $row['data']['description'] = $normalized_description;
            $row['data']['threat_description'] = $normalized_description;
            $row['data']['summary'] = $normalized_description;
            $row['details'] = $normalized_description;
            $row['description'] = $normalized_description;
        }

        if ( empty( $row['threat_type'] ) && isset( $row['data']['threat_type'] ) ) {
            $row['threat_type'] = $row['data']['threat_type'];
        }

        if ( empty( $row['details'] ) && isset( $row['data']['description'] ) && is_string( $row['data']['description'] ) ) {
            $row['details'] = $row['data']['description'];
        }

        if ( empty( $row['match'] ) && isset( $row['data']['match'] ) && is_string( $row['data']['match'] ) ) {
            $row['match'] = $row['data']['match'];
        }

        if ( empty( $row['match'] ) && isset( $row['data']['match_snippet'] ) && is_string( $row['data']['match_snippet'] ) ) {
            $row['match'] = $row['data']['match_snippet'];
        }

        // Restore Vulnerability Metadata (Flatten from data to root)
        $meta_fields = [ 'title', 'version', 'vnv', 'cve', 'cvss', 'fixed_in', 'affected_versions', 'description' ];
        foreach ( $meta_fields as $field ) {
            if ( isset( $row['data'][ $field ] ) ) {
                $row[ $field ] = $row['data'][ $field ];
            }
        }

        // Fallback for title if missing
        if ( empty( $row['title'] ) && ! empty( $row['message'] ) ) {
            $row['title'] = $row['message'];
        }

        // Fallback for name (UI often checks name || title)
        if ( empty( $row['name'] ) && ! empty( $row['title'] ) ) {
            $row['name'] = $row['title'];
        }

        // Inject Presentation Metadata
        try {
            $typeEnum = IssueType::tryFrom( $row['type'] ) ?? IssueType::UNKNOWN;

            $row['meta'] = [
                'layout' => $typeEnum->getLayout(),
                'label'  => $typeEnum->label(),
            ];
        } catch ( \Throwable $e ) {
            $row['meta'] = [
                'layout' => 'generic_card',
                'label'  => 'Unknown Issue',
            ];
        }

        // Backend-issued UI contract (source of truth for card copy/actions).
        $row['display'] = self::build_display_contract( $row );
        $row['action_policy'] = self::build_action_policy( $row );

        return $row;
    }

    /**
     * Build backend-provided display DTO for scanner UI.
     *
     * @param array $row
     * @return array
     */
    public static function build_display_contract( array $row ): array {
        $data = ( isset( $row['data'] ) && is_array( $row['data'] ) ) ? $row['data'] : [];
        $category = self::normalize_issue_category( (string) ( $row['type'] ?? '' ) );
        $component_type = self::infer_component_type( $row );
        $component_slug = self::infer_component_slug( $row, $component_type );
        $asset_name = self::resolve_component_asset_name( $component_type, $component_slug, $data );
        $file_path = (string) ( $row['file'] ?? $row['file_path'] ?? '' );
        $relative_path = self::normalize_relative_file_path( $file_path );
        $protection_tier = self::get_file_protection_tier( $file_path );
        $severity = sanitize_key( (string) ( $row['severity'] ?? 'medium' ) );
        if ( ! in_array( $severity, [ 'critical', 'high', 'medium', 'low' ], true ) ) {
            $severity = 'medium';
        }

        $title = trim( (string) ( $row['title'] ?? $row['message'] ?? '' ) );
        $subtitle = '';
        $description = trim( (string) ( $row['details'] ?? $row['message'] ?? '' ) );
        if ( $description === '' ) {
            $description = 'Review this finding and apply remediation if needed.';
        }

        $location_label = 'File Location';
        $location_value = $file_path !== '' ? $file_path : ( $component_slug !== '' ? $component_slug : 'System Location' );
        $location_type = 'path';
        $location_href = '';

        $context_label = 'Component';
        $context_value = self::resolve_component_context_value( $component_type, $file_path );

        switch ( $category ) {
            case 'malware':
                $title = $relative_path === 'wp-config.php'
                    ? 'Malware Detected in WordPress Configuration'
                    : 'Malicious File Detected';
                $subtitle = trim( (string) ( $row['threat_type'] ?? '' ) );
                if ( $protection_tier === 'locked' ) {
                    $manual_remediation_note = 'This finding affects wp-config.php, a protected WordPress configuration file that stores database credentials, salts, and other security-sensitive secrets. For safety, SiteFort does not allow in-app viewing, automated repair, or deletion of this file. Restore a verified clean backup or remediate it manually through your hosting file manager, SFTP, or SSH, then rerun the scan to confirm integrity.';
                    $description = $description !== ''
                        ? rtrim( $description, ". \t\n\r\0\x0B" ) . '. ' . $manual_remediation_note
                        : $manual_remediation_note;
                }
                break;

            case 'vulnerability':
                $component_name = trim( (string) ( $data['component_name'] ?? $data['asset_name'] ?? $row['name'] ?? $component_slug ) );
                if ( $component_name === '' ) {
                    $component_name = 'Unknown Component';
                }
                $title = 'Vulnerability Detected';
                $subtitle = $component_name;
                $context_label = 'Version';
                $context_value = trim( (string) ( $row['version'] ?? 'Unknown' ) );
                break;

            case 'sensitive_data':
                $title = trim( (string) ( $row['message'] ?? 'Sensitive Data Exposure' ) );
                $subtitle = trim( (string) ( $data['exposure_value'] ?? 'Sensitive Data Exposure' ) );
                $location_label = 'Exposed File';
                $context_label = trim( (string) ( $data['exposure_label'] ?? 'Exposure Type' ) );
                $context_value = trim( (string) ( $data['exposure_value'] ?? 'Publicly Accessible File' ) );
                break;

            case 'blocklist':
                $title = trim( (string) ( $data['title'] ?? $row['message'] ?? 'Reputation Issue Detected' ) );
                $has_ip = isset( $data['ip'] ) || isset( $data['listed_on'] );
                $has_domain = isset( $data['domain'] );

                if ( $has_ip ) {
                    $ip = trim( (string) ( $data['ip'] ?? '' ) );
                    $listed_on = is_array( $data['listed_on'] ?? null ) ? $data['listed_on'] : [];
                    $sources = ! empty( $listed_on ) ? implode( ', ', $listed_on ) : 'DNS Blocklist';
                    $subtitle = $ip !== '' ? sprintf( '%s listed on %s', $ip, $sources ) : $sources;
                    $location_label = 'Detected By';
                    $location_value = $sources;
                    $location_type = 'text';
                    $context_label = '';
                    $context_value = '';
                    $description = sprintf(
                        'Your server IP (%s) is listed on %s. This can cause email delivery failures, reduced search engine trust, and may indicate that your server or a neighbor on the same IP has been used for spam or malicious activity.',
                        $ip !== '' ? $ip : 'unknown',
                        $sources
                    );
                } elseif ( $has_domain ) {
                    $domain_val = trim( (string) ( $data['domain'] ?? '' ) );
                    $impact = trim( (string) ( $data['impact'] ?? '' ) );
                    $proof = ( isset( $data['proof'] ) && is_array( $data['proof'] ) ) ? $data['proof'] : [];
                    $subtitle = $domain_val !== '' ? sprintf( '%s flagged by security vendors', $domain_val ) : 'Domain flagged by security vendors';
                    $location_label = 'Detected By';
                    $location_value = ! empty( $proof ) ? implode( ', ', array_keys( $proof ) ) : 'Security Vendors';
                    $location_type = 'text';
                    $context_label = '';
                    $context_value = '';
                    $description = $impact !== '' ? $impact : sprintf( 'Your domain (%s) has been flagged by security vendors. Visitors may see browser warnings, and search engines may penalize your site.', $domain_val );
                } elseif ( isset( $data['proof'] ) || isset( $data['impact'] ) ) {
                    $impact = trim( (string) ( $data['impact'] ?? '' ) );
                    $proof = ( isset( $data['proof'] ) && is_array( $data['proof'] ) ) ? $data['proof'] : [];
                    $flagged_domains = ! empty( $proof ) ? array_keys( $proof ) : [];
                    $subtitle = ! empty( $flagged_domains ) ? sprintf( '%s linked to blacklisted domains', implode( ', ', $flagged_domains ) ) : 'Blacklisted external domains referenced on your site';
                    $location_label = 'Flagged Domains';
                    $location_value = ! empty( $flagged_domains ) ? implode( ', ', $flagged_domains ) : 'External Links';
                    $location_type = 'text';
                    $context_label = 'Impact';
                    $context_value = $impact !== '' ? $impact : 'Blacklisted domains referenced on site';
                    $description = $impact !== '' ? $impact : 'Your site links to domains flagged by security vendors. These links may harm your reputation and put visitors at risk.';
                } else {
                    $subtitle = $file_path !== '' ? $file_path : 'Reputation Check';
                    $context_label = 'Source';
                    $context_value = $subtitle;
                }
                break;

            case 'user':
                $user_login = trim( (string) ( $data['user_login'] ?? $location_value ) );
                $reason = self::resolve_user_reason( $row );
                if ( $reason === 'weak_password' ) {
                    $title = 'Weak Password Detected';
                    $subtitle = '';
                    $description = 'This account is using a password that matches a known weak or commonly breached pattern. Passwords in this category materially increase the likelihood of unauthorized access.';
                } elseif ( $reason === 'hidden_privileged_user' ) {
                    $title = 'Privileged Account Hidden from User Listings';
                    $subtitle = '';
                    $description = 'This account has privileged access but does not appear in one or more standard WordPress user listings. This pattern can indicate an attempt to avoid detection inside the WordPress admin area.';
                } elseif ( $reason === 'shadow_manage_capability' ) {
                    $title = 'Administrative Access Assigned Directly to Non-Administrator Account';
                    $subtitle = '';
                    $description = 'This account was granted administrative control over key WordPress settings directly, without the standard Administrator role. This pattern is more consistent with manual privilege manipulation than with a normal role assignment.';
                } elseif ( $reason === 'inconsistent_privileged_user_level' ) {
                    $title = 'Administrator Permission Data Mismatch';
                    $subtitle = '';
                    $description = 'The internal permission data on this account does not match the values WordPress normally writes during account creation. This inconsistency suggests the permissions were altered outside the standard WordPress flow.';
                } elseif ( $reason === 'privileged_creation_event_anomaly' ) {
                    $title = 'Unauthorized Admin Privilege Change';
                    $subtitle = '';
                    $description = 'This account was promoted to administrator without any signed-in user performing the change. That pattern is a strong indicator of unauthorized privilege assignment through a script, exploit, or direct database change.';
                } elseif ( $reason === 'malformed_privileged_capability_meta' ) {
                    $title = 'Unexpected Administrator Permission Data';
                    $subtitle = '';
                    $description = 'A database entry grants administrator access to this account, but the stored permission data is not formatted the way WordPress normally writes it. This usually indicates direct database modification or data corruption.';
                } elseif ( $reason === 'ghost_users' ) {
                    $title = 'Hidden User Accounts Detected';
                    $subtitle = '';
                    $description = 'The number of accounts visible on the WordPress Users screen does not match the number stored in the database. This usually means one or more accounts have been concealed from the admin interface. Review the user records directly in the database.';
                } elseif ( $reason === 'scan_timeout' ) {
                    $title = 'User Audit Incomplete';
                    $subtitle = '';
                    $description = 'The user audit did not finish within the server execution window. Increase PHP max_execution_time on the host and run the scan again.';
                } elseif ( in_array( $reason, [ 'privileged_account_scan_failed', 'user_intelligence_sync_failed', 'password_dictionary_sync_failed', 'scan_failed' ], true ) ) {
                    $title = 'User Audit Failed';
                    $subtitle = '';
                    if ( $description === '' || $description === (string) ( $row['message'] ?? '' ) ) {
                        $description = 'The user audit stopped before all account checks completed. Rerun the scan once the underlying service issue is resolved.';
                    }
                } elseif ( $reason === 'pattern_and_meta' ) {
                    $title = 'Suspicious Administrator Account';
                    $subtitle = '';
                    $description = 'This administrator account uses a username pattern associated with malicious activity, and the account profile does not match a standard WordPress account setup.';
                } elseif ( $reason === 'missing_meta' ) {
                    $title = 'Suspicious User Account';
                    $subtitle = '';
                    $description = 'This account profile does not match a standard WordPress account setup and may have been created outside the normal WordPress flow.';
                } elseif ( $reason === 'pattern_match' ) {
                    $is_admin_account = in_array( 'administrator', (array) ( $data['roles'] ?? [] ), true );
                    $title = $is_admin_account ? 'Suspicious Administrator Username' : 'Suspicious Username';
                    $subtitle = '';
                    $description = $is_admin_account
                        ? 'An administrator account is using a username pattern associated with malicious or automated account creation. Administrator accounts are high-value targets; confirm you created this account and remove it if it is unexpected.'
                        : 'This username matches patterns associated with malicious or automated account creation.';
                } else {
                    $title = 'Account Requires Review';
                    $subtitle = '';
                    if ( $description === '' || $description === (string) ( $row['message'] ?? '' ) ) {
                        $description = 'This account has security-relevant profile or permission anomalies.';
                    }
                }
                if ( $title === '' ) {
                    $title = 'Account Requires Review';
                }
                $location_label = 'User';
                $location_value = $user_login !== '' ? $user_login : 'Unknown User';
                $context_label = 'Detection Reason';
                switch ( $reason ) {
                    case 'weak_password':
                        $context_value = 'Weak Password Match';
                        break;
                    case 'pattern_and_meta':
                        $context_value = 'Suspicious Pattern + Metadata Anomaly';
                        break;
                    case 'missing_meta':
                        $context_label = 'Review Trigger';
                        $context_value = 'Account profile may have been created outside the normal WordPress flow';
                        break;
                    case 'pattern_match':
                        $context_value = 'Suspicious Username Pattern';
                        break;
                    case 'hidden_privileged_user':
                        $context_value = 'Privileged Account Hidden from User Listings';
                        break;
                    case 'shadow_manage_capability':
                        $context_value = 'Elevated Privileges Outside Admin Role';
                        break;
                    case 'inconsistent_privileged_user_level':
                        $context_value = 'Tampered Admin Permission Data';
                        break;
                    case 'privileged_creation_event_anomaly':
                        $context_label = 'Review Trigger';
                        $context_value = 'Administrator privileges were granted without a signed-in administrator action';
                        break;
                    case 'malformed_privileged_capability_meta':
                        $context_value = 'Corrupted Admin Permission Record';
                        break;
                    case 'ghost_users':
                        $context_value = 'Account Count Does Not Match Database';
                        break;
                    case 'scan_timeout':
                        $context_value = 'User Audit Incomplete';
                        break;
                    case 'privileged_account_scan_failed':
                    case 'user_intelligence_sync_failed':
                    case 'password_dictionary_sync_failed':
                    case 'scan_failed':
                        $context_value = 'User Audit Failed';
                        break;
                    default:
                        $context_value = 'Account Security Anomaly';
                        break;
                }
                if ( in_array( $reason, [ 'scan_timeout', 'privileged_account_scan_failed', 'user_intelligence_sync_failed', 'password_dictionary_sync_failed', 'scan_failed' ], true ) ) {
                    $location_label = 'Component';
                    $location_value = 'System Users';
                }
                if ( $reason === 'ghost_users' ) {
                    $location_label = 'Component';
                    $location_value = 'User Accounts Database';
                }
                break;

            case 'skipped':
                $status = sanitize_key( (string) ( $row['status'] ?? '' ) );
                $reason = sanitize_key( (string) ( $data['reason'] ?? '' ) );
                $component = sanitize_key( (string) ( $data['component'] ?? '' ) );
                if ( ( $status === 'scan_timeout' || $reason === 'scan_timeout' )
                    && ( $component === 'users' || isset( $data['last_page'] ) || isset( $data['last_user'] ) ) ) {
                    $title = 'User Audit Incomplete';
                    $subtitle = 'Scan timed out before all users were checked';
                    $context_label = 'Detection Context';
                    $context_value = 'User Audit Incomplete';
                    $location_label = 'Component';
                    $location_value = 'System Users';
                    if ( $description === '' || $description === (string) ( $row['message'] ?? '' ) ) {
                        $description = 'The user audit could not complete within server execution limits. Increase PHP max_execution_time and rerun the scan.';
                    }
                } elseif ( $component === 'users' && $status === 'failed' ) {
                    $title = 'User Audit Failed';
                    $subtitle = 'Account scan did not complete';
                    $context_label = 'Detection Context';
                    $context_value = 'User Audit Failed';
                    $location_label = 'Component';
                    $location_value = 'System Users';
                    if ( $description === '' ) {
                        $description = 'The user audit failed before all account checks completed. Rerun the scan after the service issue is resolved.';
                    }
                } elseif ( $status === 'too_large' ) {
                    $title = 'File too large to scan';
                    $subtitle = 'Exceeds maximum scan size';
                    $size_label = trim( (string) ( $data['size_label'] ?? '' ) );
                    $limit_label = trim( (string) ( $data['limit_label'] ?? '' ) );
                    if ( $size_label !== '' && $limit_label !== '' ) {
                        $description = sprintf( 'This file is %s and exceeds the %s scan limit, so it was not analyzed for threats. Review it manually and delete it if it is unfamiliar or suspicious.', $size_label, $limit_label );
                    } else {
                        $description = 'This file exceeds the maximum scan size and was not analyzed for threats. Review it manually and delete it if it is unfamiliar or suspicious.';
                    }
                } else {
                    if ( $title === '' ) {
                        $title = 'Item Skipped';
                    }
                    switch ( $status ) {
                        case 'unreadable':
                            $subtitle = 'Unreadable';
                            break;
                        default:
                            $subtitle = 'Not Scanned';
                            break;
                    }
                }
                break;

            case 'content':
                $title = trim( (string) ( $row['message'] ?? 'Suspicious Content Detected' ) );
                $subtitle = trim( (string) ( $data['post_title'] ?? $data['option_name'] ?? '' ) );
                $table = sanitize_key( (string) ( $data['table'] ?? '' ) );
                switch ( $table ) {
                    case 'posts':
                        $location_label = 'Post';
                        break;
                    case 'comments':
                        $location_label = 'Comment';
                        break;
                    case 'options':
                        $location_label = 'Option';
                        break;
                    case 'postmeta':
                        $location_label = 'Post Meta';
                        break;
                    case 'usermeta':
                        $location_label = 'User Meta';
                        break;
                    case 'termmeta':
                        $location_label = 'Term Meta';
                        break;
                    default:
                        $location_label = 'Location';
                        break;
                }
                $post_url = trim( (string) ( $data['post_url'] ?? '' ) );
                if ( $post_url !== '' ) {
                    $subtitle = $post_url;
                    $location_type = 'url';
                    $location_value = $post_url;
                    $location_href = $post_url;
                }
                $context_label = 'Table';
                $context_value = $table !== '' ? ucfirst( $table ) : 'Database';
                break;

            case 'integrity':
                $status = sanitize_key( (string) ( $row['status'] ?? '' ) );
                $detection_type = sanitize_key( (string) ( $data['detection_type'] ?? '' ) );
                if ( (string) ( $row['type'] ?? '' ) === IssueType::FAKE_IMAGE || $detection_type === 'image_type_mismatch' ) {
                    $title = 'Suspicious Image File Detected';
                    $subtitle = 'Unexpected content in image file';
                    $context_label = 'Validation';
                    $context_value = self::resolve_fake_image_validation_label( $data );
                    $description = trim( (string) ( $data['description'] ?? '' ) );
                    if ( $description === '' ) {
                        $description = 'This file uses an image extension but contains content that is unexpected for an image. This can indicate a compromised upload or hidden payload. If the file is not expected, delete it and restore a clean copy from a trusted source.';
                    }
                } elseif ( $status === 'unknown' || $detection_type === 'core_unknown_file' ) {
                    $title = 'Unknown Core File Detected';
                    $subtitle = 'Unexpected file in protected core directory';
                } elseif ( $status === 'missing' ) {
                    $title = 'Core File Missing';
                    $subtitle = 'WordPress file not found';
                } elseif ( $title === '' ) {
                    $title = 'File Integrity Issue Detected';
                }
                if ( self::is_checksum_mismatch_integrity_issue( $row, $data ) ) {
                    $description = self::build_integrity_display_description(
                        $component_type,
                        $asset_name,
                        trim( (string) ( $data['version'] ?? '' ) ),
                        $description
                    );
                }
                break;

            case 'failed':
                $title = 'Scan Notice';
                $subtitle = 'A background scan task did not complete';
                $context_label = 'Detection Context';
                $context_value = 'Scan Diagnostic';
                $location_label = 'Component';
                $location_value = 'Scanner';
                break;

            default:
                if ( $title === '' ) {
                    $title = 'Security Issue Detected';
                }
                $subtitle = self::resolve_status_subtitle( (string) ( $row['status'] ?? '' ) );
                if ( $subtitle === '' ) {
                    $subtitle = 'Review recommended';
                }
                break;
        }

        if ( $title === '' ) {
            $title = 'Security Issue Detected';
        }
        if ( $subtitle === '' ) {
            $subtitle = self::resolve_status_subtitle( (string) ( $row['status'] ?? '' ) );
        }

        $created_at = (int) ( $row['created_at'] ?? 0 );
        if ( $created_at <= 0 ) {
            $created_at = time();
        }
        $last_modified_raw = $data['last_modified'] ?? null;
        $last_modified = is_numeric( $last_modified_raw ) ? (int) $last_modified_raw : null;
        $type_label = trim( (string) ( $row['meta']['label'] ?? '' ) );
        if ( $type_label === '' ) {
            $type_label = ucfirst( $category );
        }

        $display = [
            'title'       => $title,
            'subtitle'    => $subtitle,
            'description' => $description,
            'location'    => [
                'label' => $location_label,
                'value' => $location_value,
                'type'  => $location_type,
            ],
            'context'     => [
                'label' => $context_label,
                'value' => $context_value,
            ],
            'meta'        => [
                'severity'   => $severity,
                'created_at' => $created_at,
                'type_label' => $type_label,
            ],
        ];

        if ( $location_href !== '' ) {
            $display['location']['href'] = $location_href;
        }
        if ( $last_modified !== null && $last_modified > 0 ) {
            $display['meta']['last_modified'] = $last_modified;
        }

        if ( $category === 'blocklist' ) {
            $proof = ( isset( $data['proof'] ) && is_array( $data['proof'] ) ) ? $data['proof'] : [];
            $sources = [];
            foreach ( $proof as $key => $val ) {
                if ( is_string( $val ) && $val !== '' ) {
                    $sources[] = [ 'name' => (string) $key, 'url' => $val ];
                } elseif ( is_array( $val ) ) {
                    foreach ( $val as $vendor => $url ) {
                        if ( is_string( $url ) && $url !== '' ) {
                            $sources[] = [ 'name' => sprintf( '%s (%s)', (string) $key, (string) $vendor ), 'url' => $url ];
                        }
                    }
                }
            }
            if ( ! empty( $sources ) ) {
                $display['meta']['sources'] = $sources;
            }
        }

        return $display;
    }

    /**
     * @param string $file_path Absolute or ABSPATH-relative file path.
     * @return string|null 'locked', 'download_first', or null.
     */
    private static function get_file_protection_tier( string $file_path ): ?string {
        $relative = self::normalize_relative_file_path( $file_path );
        if ( $relative === '' ) {
            return null;
        }
        if ( $relative === 'wp-config.php' ) {
            return 'locked';
        }
        if ( in_array( $relative, self::get_server_config_relative_files(), true ) ) {
            return 'download_first';
        }
        return null;
    }

    /**
     * Build backend action policy contract for issue cards.
     *
     * @param array $row
     * @return array
     */
    public static function build_action_policy( array $row ): array {
        $data = self::normalize_row_data( $row );
        $row['data'] = $data;
        $category = self::normalize_issue_category( (string) ( $row['type'] ?? '' ) );
        $component_type = self::infer_component_type( $row );
        $file_path = (string) ( $row['file'] ?? $row['file_path'] ?? '' );
        $status = sanitize_key( (string) ( $row['status'] ?? '' ) );
        $detection_type = sanitize_key( (string) ( $data['detection_type'] ?? '' ) );
        $policy_reason = sanitize_key( (string) ( $data['policy_reason'] ?? '' ) );
        $is_fake_image_issue = (string) ( $row['type'] ?? '' ) === IssueType::FAKE_IMAGE || $detection_type === 'image_type_mismatch';
        $is_nonbaseline_integrity_file = self::is_nonbaseline_integrity_file( $category, $component_type, $status, $detection_type, $policy_reason );
        $is_ignored = ! empty( $row['is_ignored'] );

        $extension = self::get_file_extension( $file_path );
        $viewable_extensions = [ 'php', 'js', 'css', 'txt', 'html', 'json' ];
        $fake_image_viewable_extensions = [ 'jpg', 'jpeg', 'png', 'gif', 'ico', 'svg', 'webp' ];
        $can_view_source        = in_array( $extension, $viewable_extensions, true )
            || ( $is_fake_image_issue && in_array( $extension, $fake_image_viewable_extensions, true ) );
        $can_mutate_file        = Capabilities::can_modify_scanner_file( $file_path, $component_type );
        $repair_entitled        = self::allowsRepair();
        $repair_supported       = array_key_exists( 'repair_available', $data ) && wp_validate_boolean( $data['repair_available'] );
        $can_fetch_clean_reference = $repair_entitled && $repair_supported;
        $can_repair             = $repair_entitled && $repair_supported && $can_mutate_file;
        $can_show_repair_upsell = ! $repair_entitled && $repair_supported && $can_mutate_file;
        $can_delete             = self::allows_delete_action( $row ) && $can_mutate_file;

        $protection_tier = self::get_file_protection_tier( $file_path );
        if ( $protection_tier === 'locked' ) {
            $can_delete = false;
            $can_repair = false;
            $can_show_repair_upsell = false;
            $can_view_source = false;
        } elseif ( $protection_tier === 'download_first' ) {
            $can_repair = false;
            $can_show_repair_upsell = false;
        }
        $can_view_diff = $can_view_source
            && $can_fetch_clean_reference
            && ! $is_nonbaseline_integrity_file
            && ! $is_fake_image_issue
            && self::supports_reference_diff( $row, $data, $category, $component_type );

        $policy = [
            'primary' => null,
            'header_secondary' => [],
            'footer' => [],
            'actions' => [],
        ];

        $quarantine_retention_days = \SiteFort\Modules\Scanner\Service\QuarantineService::get_retention_days();
        $repair_upgrade_action = [
            'disabled'             => true,
            'disabled_reason'      => self::REPAIR_UPGRADE_MESSAGE,
            'disabled_tooltip'     => self::REPAIR_UPGRADE_MESSAGE,
            'requires_entitlement' => 'repair.enabled',
            'requires_plan'        => 'pro',
            'upgrade_url'          => self::REPAIR_UPGRADE_URL,
        ];

        $build_quarantine_option = static function ( string $action_key, bool $default_checked, string $label, bool $required = false ) use ( $category, $protection_tier, $quarantine_retention_days ): ?array {
            if ( ! in_array( $category, [ 'malware', 'integrity' ], true ) ) {
                return null;
            }
            if ( $protection_tier !== null ) {
                return null;
            }

            return [
                'available'        => true,
                'default_checked'  => $default_checked,
                'label'            => $label,
                'retention_days'   => $quarantine_retention_days,
                'source_action'    => $action_key,
                'required'         => $required,
            ];
        };

        $add_action = static function ( array &$policy_ref, string $key, string $label, string $variant, string $placement = 'header', bool $requires_confirm = false, string $confirm_message = '', array $extra = [] ): void {
            $policy_ref['actions'][ $key ] = [
                'label' => $label,
                'variant' => $variant,
            ];
            if ( $requires_confirm ) {
                $policy_ref['actions'][ $key ]['requires_confirm'] = true;
            }
            if ( $confirm_message !== '' ) {
                $policy_ref['actions'][ $key ]['confirm_message'] = $confirm_message;
            }
            foreach ( $extra as $extra_key => $extra_value ) {
                $policy_ref['actions'][ $key ][ $extra_key ] = $extra_value;
            }

            if ( $placement === 'header' || $placement === 'both' ) {
                if ( ! in_array( $key, $policy_ref['header_secondary'], true ) ) {
                    $policy_ref['header_secondary'][] = $key;
                }
            }
            if ( $placement === 'footer' || $placement === 'both' ) {
                if ( ! in_array( $key, $policy_ref['footer'], true ) ) {
                    $policy_ref['footer'][] = $key;
                }
            }
        };

        $set_primary = static function ( array &$policy_ref, string $key, string $label, string $variant, bool $requires_confirm = false, string $confirm_message = '', array $extra = [] ) use ( $add_action ): void {
            $add_action( $policy_ref, $key, $label, $variant, 'header', $requires_confirm, $confirm_message, $extra );
            $policy_ref['primary'] = $key;
        };

        switch ( $category ) {
            case 'sensitive_data':
                $available_actions = [];
                if ( isset( $data['available_actions'] ) && is_array( $data['available_actions'] ) ) {
                    foreach ( $data['available_actions'] as $action_key ) {
                        if ( is_string( $action_key ) ) {
                            $available_actions[] = sanitize_key( $action_key );
                        }
                    }
                }
                $available_actions = array_values( array_unique( array_filter( $available_actions ) ) );
                $has_explicit_actions = ! empty( $available_actions );
                $supports_protect = ! $has_explicit_actions || in_array( 'protect', $available_actions, true );
                $supports_delete = ( ! $has_explicit_actions || in_array( 'delete', $available_actions, true ) ) && $can_delete;
                $supports_view = ! $has_explicit_actions || in_array( 'view', $available_actions, true );
                $preferred_action = sanitize_key( (string) ( $data['preferred_action'] ?? '' ) );

                $delete_confirm = 'Are you sure? This will permanently remove this file from your server and cannot be undone.';
                if ( $preferred_action === 'delete' && $supports_delete ) {
                    $set_primary( $policy, 'delete', 'Delete File', 'danger', true, $delete_confirm );
                } elseif ( $supports_protect ) {
                    $set_primary( $policy, 'protect', 'Protect Access', 'primary' );
                } elseif ( $supports_delete ) {
                    $set_primary( $policy, 'delete', 'Delete File', 'danger', true, $delete_confirm );
                }

                if ( $supports_delete && $policy['primary'] !== 'delete' ) {
                    $add_action( $policy, 'delete', 'Delete File', 'danger', 'header', true, $delete_confirm );
                }
                if ( $supports_protect && $policy['primary'] !== 'protect' ) {
                    $add_action( $policy, 'protect', 'Protect Access', 'primary', 'header' );
                }
                if ( $supports_view && $can_view_source ) {
                    $add_action( $policy, 'view', 'View File', 'secondary', 'footer' );
                }
                break;

            case 'malware':
                $delete_confirm_malware = 'Are you sure? This will permanently remove this file from your server and cannot be undone.';
                $requires_delete_quarantine = self::requires_delete_quarantine( $row );
                $delete_quarantine_option = $build_quarantine_option(
                    'delete',
                    $requires_delete_quarantine,
                    $requires_delete_quarantine
                        ? 'Required: save encrypted quarantine copy before deleting core file'
                        : 'Keep quarantined copy for ' . $quarantine_retention_days . ' days',
                    $requires_delete_quarantine
                );
                if ( $can_repair ) {
                    $set_primary(
                        $policy,
                        'repair',
                        'Repair File',
                        'primary',
                        false,
                        '',
                        [
                            'quarantine_option' => $build_quarantine_option( 'repair', true, 'Quarantine current file before repair' ),
                        ]
                    );
                    if ( $can_delete ) {
                        $add_action(
                            $policy,
                            'delete',
                            'Delete File',
                            'danger',
                            'header',
                            true,
                            $delete_confirm_malware,
                            [
                                'quarantine_option' => $delete_quarantine_option,
                            ]
                        );
                    }
                } elseif ( $can_show_repair_upsell ) {
                    $set_primary(
                        $policy,
                        'repair',
                        'Repair File',
                        'primary',
                        false,
                        '',
                        $repair_upgrade_action
                    );
                    if ( $can_delete ) {
                        $add_action(
                            $policy,
                            'delete',
                            'Delete File',
                            'danger',
                            'header',
                            true,
                            $delete_confirm_malware,
                            [
                                'quarantine_option' => $delete_quarantine_option,
                            ]
                        );
                    }
                } elseif ( $can_delete ) {
                    $set_primary(
                        $policy,
                        'delete',
                        'Delete File',
                        'danger',
                        true,
                        $delete_confirm_malware,
                        [
                            'quarantine_option' => $delete_quarantine_option,
                        ]
                    );
                }
                if ( $can_view_diff ) {
                    $add_action( $policy, 'view', 'View Diff', 'secondary', 'footer' );
                } elseif ( $can_view_source ) {
                    $add_action( $policy, 'view', 'View File', 'secondary', 'footer' );
                }
                break;

            case 'vulnerability':
                if ( $component_type === 'theme' ) {
                    $set_primary( $policy, 'update', 'Update Theme', 'warning' );
                } elseif ( $component_type === 'core' ) {
                    $set_primary( $policy, 'update', 'Update WordPress', 'warning' );
                } else {
                    $set_primary( $policy, 'update', 'Update Plugin', 'warning' );
                }
                break;

            case 'integrity':
                $delete_confirm_integrity = 'Are you sure? This will permanently remove this file from your server and cannot be undone.';
                if ( $is_fake_image_issue ) {
                    if ( $can_delete ) {
                        $set_primary(
	                            $policy,
	                            'delete',
	                            'Delete File',
	                            'danger',
	                            true,
	                            $delete_confirm_integrity,
	                            [
                                'quarantine_option' => $build_quarantine_option( 'delete', false, 'Keep quarantined copy for ' . $quarantine_retention_days . ' days' ),
                            ]
                        );
                    }

                    if ( $can_view_source ) {
                        $add_action( $policy, 'view', 'View File', 'secondary', 'footer' );
                    }
                } elseif ( $is_nonbaseline_integrity_file && $can_delete ) {
                    $set_primary(
                        $policy,
                        'delete',
	                        'Delete File',
	                        'danger',
                        true,
                        $delete_confirm_integrity,
                        [
                            'quarantine_option' => $build_quarantine_option( 'delete', false, 'Keep quarantined copy for ' . $quarantine_retention_days . ' days' ),
                        ]
                    );
                } elseif ( $can_repair ) {
                    $set_primary(
                        $policy,
                        'repair',
                        'Repair File',
                        'warning',
                        false,
                        '',
                        [
                            'quarantine_option' => $build_quarantine_option( 'repair', true, 'Quarantine current file before repair' ),
                        ]
                    );
                } elseif ( $can_show_repair_upsell ) {
                    $set_primary(
                        $policy,
                        'repair',
                        'Repair File',
                        'warning',
                        false,
                        '',
                        $repair_upgrade_action
                    );
                }
                if ( ! $is_fake_image_issue && $can_view_diff ) {
                    $add_action( $policy, 'view', 'View Diff', 'secondary', 'footer' );
                } elseif ( ! $is_fake_image_issue && $can_view_source ) {
                    $add_action( $policy, 'view', 'View File', 'secondary', 'footer' );
                }
                if ( $can_delete && $policy['primary'] !== 'delete' ) {
                    $add_action(
                        $policy,
                        'delete',
                        'Delete File',
                        'danger',
                        'header',
                        true,
                        $delete_confirm_integrity,
                        [
                            'quarantine_option' => $build_quarantine_option( 'delete', false, 'Keep quarantined copy for ' . $quarantine_retention_days . ' days' ),
                        ]
                    );
                }
                break;

            case 'content':
                if ( ! empty( $data['edit_url'] ) ) {
                    $table = sanitize_key( (string) ( $data['table'] ?? '' ) );
                    $label = ( $table === 'comments' ) ? 'Edit Comment' : ( $table === 'posts' ? 'Edit Post' : 'Edit' );
                    $set_primary( $policy, 'edit', $label, 'warning' );
                }
                break;

            case 'user':
                $reason = self::resolve_user_reason( $row );
                $user_id = $data['user_id'] ?? null;
                $metadata_review_reasons = [ 'malformed_privileged_capability_meta', 'inconsistent_privileged_user_level' ];
                if ( is_numeric( $user_id ) && (int) $user_id > 0 ) {
                    $target_user_id = (int) $user_id;
                    if ( in_array( $reason, $metadata_review_reasons, true ) ) {
                        if ( self::can_edit_user_remediation_target( $target_user_id ) ) {
                            $set_primary( $policy, 'edit_user', 'Review User', 'primary' );
                        }
                    } elseif ( self::can_delete_user_remediation_target( $target_user_id ) ) {
                        $set_primary(
                            $policy,
                            'delete_user',
                            'Delete User',
                            'danger',
                            true,
                            'Are you sure you want to delete this user? This action cannot be undone.'
                        );
                    }
                    if ( self::can_edit_user_remediation_target( $target_user_id ) ) {
                        if ( $reason === 'weak_password' ) {
                            $add_action( $policy, 'update_password', 'Update Password', 'secondary', 'header' );
                        } elseif ( $policy['primary'] !== 'edit_user' ) {
                            $add_action( $policy, 'edit_user', 'Edit User', 'secondary', 'header' );
                        }
                    }
                } elseif ( $reason === 'ghost_users' ) {
                    $set_primary( $policy, 'view_db', 'Review Users', 'primary' );
                }
                break;

            case 'skipped':
                if ( $can_delete ) {
                    $set_primary( $policy, 'delete', 'Delete File', 'danger', true, 'Are you sure? This will permanently remove this file from your server and cannot be undone.' );
                }
                break;

            default:
                if ( $can_view_source ) {
                    $add_action( $policy, 'view', 'View File', 'secondary', 'footer' );
                }
                break;
        }

        if ( $protection_tier === 'download_first' && $file_path !== '' ) {
            if ( $policy['primary'] === null ) {
                $set_primary( $policy, 'download', 'Download Copy', 'secondary' );
            } else {
                $add_action( $policy, 'download', 'Download Copy', 'secondary', 'header' );
            }
            if ( isset( $policy['actions']['delete'] ) ) {
                $policy['actions']['delete']['confirm_message'] = 'Please download a backup copy of this file first. Deleting this file may affect your site\'s URL routing, access rules, or firewall protection. This action cannot be undone.';
            }
        }

        $add_action( $policy, 'fixed', 'Mark as Fixed', 'success', 'footer' );
        if ( $is_ignored ) {
            $add_action( $policy, 'unignore', 'Stop Ignoring', 'secondary', 'header' );
        } else {
            $add_action( $policy, 'ignore', 'Ignore', 'secondary', 'header' );
        }

        if ( is_string( $policy['primary'] ) && $policy['primary'] !== '' ) {
            $policy['header_secondary'] = array_values(
                array_filter(
                    $policy['header_secondary'],
                    static fn( $key ) => $key !== $policy['primary']
                )
            );
            $policy['footer'] = array_values(
                array_filter(
                    $policy['footer'],
                    static fn( $key ) => $key !== $policy['primary']
                )
            );
        }

        return $policy;
    }

    /**
     * Normalize low-level issue type to UI category.
     *
     * @param string $type
     * @return string
     */
    private static function normalize_issue_category( string $type ): string {
        $type = sanitize_key( strtolower( $type ) );

        switch ( $type ) {
            case 'malware':
                return 'malware';
            case 'user':
                return 'user';
            case 'content':
            case 'content_group':
            case 'post':
            case 'posts':
            case 'page':
            case 'comment':
            case 'comments':
            case 'option':
            case 'options':
            case 'postmeta':
            case 'usermeta':
            case 'termmeta':
                return 'content';
            case 'vulnerability':
            case 'vulnerability_group':
                return 'vulnerability';
            case 'sensitive_data':
                return 'sensitive_data';
            case 'integrity':
            case 'fake_image':
            case 'core':
            case 'modified':
                return 'integrity';
            case 'blocklist':
                return 'blocklist';
            case 'site_health':
            case 'hardening':
                return 'hardening';
            case 'system_error':
            case 'failed':
                return 'failed';
            case 'skipped':
                return 'skipped';
            default:
                return 'unknown';
        }
    }

    /**
     * Infer component type from issue payload.
     *
     * @param array $row
     * @return string
     */
    private static function infer_component_type( array $row ): string {
        $data = ( isset( $row['data'] ) && is_array( $row['data'] ) ) ? $row['data'] : [];
        $from_data = sanitize_key( (string) ( $data['component_type'] ?? '' ) );
        if ( in_array( $from_data, [ 'plugin', 'theme', 'uploads' ], true ) ) {
            return $from_data;
        }

        $path = (string) ( $row['file'] ?? $row['file_path'] ?? '' );
        if ( $path === '' ) {
            return $from_data === 'core' ? 'core' : 'unknown';
        }

        $normalized_path = strtolower( self::normalize_relative_file_path( $path ) );
        if ( $normalized_path === '' ) {
            $normalized_path = strtolower( ltrim( wp_normalize_path( $path ), '/' ) );
        }

        if (
            $from_data === 'core'
            && (
                strpos( $normalized_path, 'wp-admin/' ) === 0
                || strpos( $normalized_path, 'wp-includes/' ) === 0
                || self::is_known_root_core_file( $normalized_path )
                || self::is_root_core_integrity_finding( $row, $normalized_path )
            )
        ) {
            return 'core';
        }

        if ( strpos( $normalized_path, 'wp-content/plugins/' ) === 0 ) {
            return 'plugin';
        }
        if ( strpos( $normalized_path, 'wp-content/themes/' ) === 0 ) {
            return 'theme';
        }
        if ( strpos( $normalized_path, 'wp-content/uploads/' ) === 0 ) {
            return 'uploads';
        }
        if (
            strpos( $normalized_path, 'wp-admin/' ) === 0
            || strpos( $normalized_path, 'wp-includes/' ) === 0
            || self::is_known_root_core_file( $normalized_path )
            || self::is_root_core_integrity_finding( $row, $normalized_path )
        ) {
            return 'core';
        }

        return 'unknown';
    }

    /**
     * Infer component slug from row metadata/path.
     *
     * @param array $row
     * @param string $component_type
     * @return string
     */
    private static function infer_component_slug( array $row, string $component_type ): string {
        $data = ( isset( $row['data'] ) && is_array( $row['data'] ) ) ? $row['data'] : [];
        $slug = sanitize_key( (string) ( $row['slug'] ?? $data['slug'] ?? '' ) );
        if ( $slug !== '' ) {
            return $slug;
        }

        $path = (string) ( $row['file'] ?? $row['file_path'] ?? '' );
        if ( $path === '' ) {
            return '';
        }

        $needle = $component_type === 'plugin' ? '/plugins/' : ( $component_type === 'theme' ? '/themes/' : '' );
        if ( $needle === '' || strpos( $path, $needle ) === false ) {
            return '';
        }

        $parts = explode( $needle, $path, 2 );
        if ( count( $parts ) < 2 ) {
            return '';
        }
        $tail = explode( '/', ltrim( $parts[1], '/' ) );
        return sanitize_key( (string) ( $tail[0] ?? '' ) );
    }

    /**
     * Resolve user finding reason from data/legacy id patterns.
     *
     * @param array $row
     * @return string
     */
    private static function resolve_user_reason( array $row ): string {
        $data = ( isset( $row['data'] ) && is_array( $row['data'] ) ) ? $row['data'] : [];
        $reason = sanitize_key( (string) ( $data['reason'] ?? '' ) );
        if ( in_array( $reason, [
            'scan_timeout',
            'pattern_and_meta',
            'missing_meta',
            'pattern_match',
            'weak_password',
            'ghost_users',
            'scan_failed',
            'privileged_account_scan_failed',
            'user_intelligence_sync_failed',
            'password_dictionary_sync_failed',
            'hidden_privileged_user',
            'shadow_manage_capability',
            'inconsistent_privileged_user_level',
            'privileged_creation_event_anomaly',
            'malformed_privileged_capability_meta',
        ], true ) ) {
            return $reason;
        }

        $issue_id = strtolower( (string) ( $row['id'] ?? $row['issue_hash'] ?? '' ) );
        if ( strpos( $issue_id, 'weak_password_' ) === 0 ) {
            return 'weak_password';
        }
        if ( strpos( $issue_id, 'malicious_admin_' ) === 0 ) {
            return 'pattern_and_meta';
        }
        if ( strpos( $issue_id, 'script_admin_' ) === 0 ) {
            return 'missing_meta';
        }
        if ( strpos( $issue_id, 'suspicious_user_' ) === 0 ) {
            return 'pattern_match';
        }
        if ( $issue_id === 'ghost_users_count' ) {
            return 'ghost_users';
        }
        if ( strpos( $issue_id, 'hidden_privileged_user_' ) === 0 ) {
            return 'hidden_privileged_user';
        }
        if ( strpos( $issue_id, 'shadow_manage_capability_' ) === 0 ) {
            return 'shadow_manage_capability';
        }
        if ( strpos( $issue_id, 'inconsistent_privileged_user_level_' ) === 0 ) {
            return 'inconsistent_privileged_user_level';
        }
        if ( strpos( $issue_id, 'privileged_creation_event_anomaly_' ) === 0 ) {
            return 'privileged_creation_event_anomaly';
        }
        if ( strpos( $issue_id, 'malformed_privileged_capability_meta_' ) === 0 ) {
            return 'malformed_privileged_capability_meta';
        }
        if ( $issue_id === 'user_scan_timeout' ) {
            return 'scan_timeout';
        }

        $hidden_count = $data['hidden_count'] ?? null;
        if ( is_numeric( $hidden_count ) && (int) $hidden_count > 0 ) {
            return 'ghost_users';
        }

        $last_page = $data['last_page'] ?? null;
        $last_user = $data['last_user'] ?? null;
        if ( ( is_numeric( $last_page ) && (int) $last_page > 0 )
            || ( is_numeric( $last_user ) && (int) $last_user > 0 )
            || ( is_string( $last_user ) && trim( $last_user ) !== '' ) ) {
            return 'scan_timeout';
        }

        return 'unknown';
    }

    /**
     * Extract lowercase file extension from path.
     *
     * @param string $path
     * @return string
     */
    private static function get_file_extension( string $path ): string {
        if ( $path === '' || strpos( $path, '.' ) === false ) {
            return '';
        }
        $ext = pathinfo( $path, PATHINFO_EXTENSION );
        return sanitize_key( strtolower( (string) $ext ) );
    }
}
