<?php

declare(strict_types=1);

namespace SecurWP\Modules\Scanner\Queue\Handler;

use SecurWP\Modules\Scanner\Queue\ScanOrchestrator;
use SecurWP\Modules\Scanner\Queue\ScanQueue;
use SecurWP\Modules\Scanner\ScanController;

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

/**
 * Runs one non-file system check.
 */
class SystemCheckHandler {

	/**
	 * @param array<string,mixed> $task
	 * @param string              $scan_id
	 * @return TaskResult
	 */
	public function handle( array $task, string $scan_id ): TaskResult {
		$queue = ScanQueue::get_job( $scan_id );
		if ( ! is_array( $queue ) || ! in_array( (string) ( $queue['status'] ?? '' ), [ 'pending', 'running' ], true ) ) {
			return TaskResult::completed( [ 'status' => 'idle' ] );
		}

		$payload = is_array( $task['payload'] ?? null ) ? $task['payload'] : [];
		$check_slug = sanitize_key( (string) ( $payload['check_slug'] ?? '' ) );
		if ( '' === $check_slug ) {
			return TaskResult::completed( [ 'status' => 'skipped' ] );
		}

		$controller = $this->ensure_controller();
		if ( ! $controller instanceof ScanController ) {
			ScanQueue::fail(
				'Scanner controller is unavailable in system check context. Please restart the scan.',
				[
					'error_code'        => 'controller_unavailable',
					'stage'             => 'system_checks',
					'retryable'         => true,
					'status_code'       => 500,
					'technical_message' => 'ScanController bootstrap failed for system check task',
				]
			);

			return TaskResult::completed( [ 'status' => 'failed' ] );
		}

		ScanQueue::set_component_status( $check_slug, 'active', 8 );

		try {
			$scan_result = $controller->run_scan( $check_slug, $scan_id );
			$check_failed = is_array( $scan_result ) && ! empty( $scan_result['failed'] );
			$check_complete = ! is_array( $scan_result ) || ! array_key_exists( 'complete', $scan_result )
				? true
				: (bool) $scan_result['complete'];

			$follow_ups = [];

			if ( $check_failed ) {
				ScanQueue::set_component_status( $check_slug, 'failed' );
			} elseif ( $check_complete ) {
				ScanQueue::set_component_status( $check_slug, 'complete' );
			} else {
				ScanQueue::set_component_status( $check_slug, 'pending' );
				$follow_ups[] = [
					'task_type'    => 'system_check',
					'payload'      => [ 'check_slug' => $check_slug ],
					'available_at' => time(),
					'priority'     => ScanQueue::SYSTEM_CHECK_PRIORITY,
					'dedupe_key'   => 'syscheck:' . $check_slug,
				];
			}

			$orchestrator = new ScanOrchestrator( $scan_id, $controller );
			if ( $orchestrator->is_ready_for_finalize() ) {
				$follow_ups[] = [
					'task_type'    => 'finalize',
					'payload'      => [ 'scan_id' => $scan_id ],
					'available_at' => time(),
					'priority'     => 10,
					'dedupe_key'   => 'finalize',
				];
			}

			return TaskResult::completed(
				[
					'status'      => $check_failed ? 'failed' : ( $check_complete ? 'completed' : 'pending' ),
					'check_slug'  => $check_slug,
				],
				$follow_ups
			);
		} catch ( \Throwable $e ) {
			ScanQueue::set_component_status( $check_slug, 'failed' );
			return TaskResult::failed( sanitize_text_field( $e->getMessage() ) );
		}
	}

	/**
	 * @return ScanController|null
	 */
	private function ensure_controller(): ?ScanController {
		if ( ! class_exists( ScanController::class ) ) {
			require_once dirname( __DIR__, 2 ) . '/ScanController.php';
		}

		if ( ! class_exists( ScanController::class ) || ! method_exists( ScanController::class, 'build_default_controller' ) ) {
			return null;
		}

		try {
			return ScanController::build_default_controller();
		} catch ( \Throwable $e ) {
			return null;
		}
	}
}
