<?php

declare(strict_types=1);

namespace SiteFort\Modules\Scanner;

use SiteFort\Modules\Scanner\Repository\IssueRepository;
use SiteFort\Includes\SettingsStore;

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


/**
 * Manages the execution of scans and result retrieval.
 * Uses IssueRepository for normalized issue persistence.
 */
class ScanController {

    /**
     * @var ScanEngine[]
     */
    private $scanners = [];

    public function __construct() {}

    /**
     * Ignore an issue by hash.
     *
     * @param string $hash Issue hash.
     * @return bool Success.
     */
    public function ignore_item( $hash ) {
        if ( IssueRepository::ignore( $hash ) ) {
            // Log to audit trail
            \SiteFort\Modules\AuditLog\AuditLog::add_log( 'Issue Ignored', [ 'hash' => $hash ], 'info', 'scanner' );
            return true;
        }
        return false;
    }

    /**
     * Unignore an issue by hash.
     *
     * @param string $hash Issue hash.
     * @return bool Success.
     */
    public function unignore_item( $hash ) {
        if ( IssueRepository::unignore( $hash ) ) {
            // Log to audit trail
            \SiteFort\Modules\AuditLog\AuditLog::add_log( 'Issue Unignored', [ 'hash' => $hash ], 'info', 'scanner' );
            return true;
        }
        return false;
    }

    /**
     * Register a scanner engine.
     */
    public function register_scanner( $slug, $scanner ) {
        $this->scanners[$slug] = $scanner;
    }

    /**
     * Build a controller with the built-in system-check scanners.
     *
     * @return self
     */
    public static function build_default_controller(): self {
        $controller = new self();
        $controller->register_scanner( 'reputation', new ReputationScanner() );
        $controller->register_scanner( 'users', new UserScanner() );
        $controller->register_scanner( 'content', new ContentScanner() );
        $controller->register_scanner( 'sensitive_data', new SensitiveDataScanner() );
        $controller->register_scanner( 'vulnerabilities', new VulnerabilityScanner() );

        return $controller;
    }

    /**
     * Run a specific scanner by slug.
     * Called by SystemCheckHandler for system checks.
     *
     * @param string $slug Scanner slug
     * @param string $scan_id Current scan session ID
     * @return array Scan results with 'issues' array
     */
    public function run_scan( $slug, $scan_id = null ) {
        if ( ! isset( $this->scanners[$slug] ) ) {
            return [ 'issues' => [], 'complete' => true, 'failed' => false ];
        }

        $scanner = $this->scanners[$slug];

        if ( method_exists( $scanner, 'set_controller' ) ) {
            $scanner->set_controller( $this );
        }
        if ( method_exists( $scanner, 'set_scan_context' ) ) {
            $scanner->set_scan_context( $scan_id );
        }

        $result = $scanner->run();
        // Handle both return formats: ['issues' => [...]] or direct array.
        $issues = isset( $result['issues'] ) ? $result['issues'] : ( is_array( $result ) ? $result : [] );
        $is_complete = true;
        $is_failed = false;
        if ( is_array( $result ) ) {
            if ( array_key_exists( 'complete', $result ) ) {
                $is_complete = (bool) $result['complete'];
            }
            if ( ! empty( $result['failed'] ) ) {
                $is_failed = true;
            }
        }

        if ( ! empty( $issues ) && $scan_id ) {
            foreach ( $issues as $issue ) {
                if ( ! isset( $issue['scan_id'] ) ) $issue['scan_id'] = $scan_id;
                IssueRepository::stage( $issue );
            }
        }

        return [
            'issues' => $issues,
            'complete' => $is_complete,
            'failed' => $is_failed,
        ];
    }

    /**
     * Refresh scanner counts and broadcast an issue-state change.
     *
     * @param string $action
     * @param string $item_hash
     * @return void
     */
    public static function emit_issue_state_change( string $action, string $item_hash ): void {
        $counts = IssueRepository::getCounts();
        $active_count = is_array( $counts ) ? (int) ( $counts['active'] ?? 0 ) : 0;

        SettingsStore::set_field(
            SettingsStore::COL_STATE,
            'scan_issues_count',
            $active_count
        );

        do_action(
            'sitefort_scan_results_changed',
            [
                'action'       => $action,
                'issue_hash'   => $item_hash,
                'active_count' => $active_count,
            ]
        );
    }

}
