<?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\Repository\IssueRepository;
use SecurWP\Modules\Scanner\Repository\TaskQueueRepository;

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

/**
 * Final scan publication task.
 */
class FinalizeHandler {

	/**
	 * @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' ] );
		}

		if ( ! class_exists( TaskQueueRepository::class ) ) {
			require_once dirname( __DIR__, 2 ) . '/Repository/TaskQueueRepository.php';
		}

		$task_repo = new TaskQueueRepository();
		$dead_tasks = $task_repo->get_dead_tasks( $scan_id );
		$orchestrator = new ScanOrchestrator( $scan_id );
		if ( ! $orchestrator->is_ready_for_finalize() ) {
			return TaskResult::completed(
				[
					'status'  => 'deferred',
					'message' => 'Finalize gate not yet satisfied',
				]
			);
		}

		$this->stage_dead_task_issues( $scan_id, $dead_tasks );
		if ( ! class_exists( '\SecurWP\Modules\Scanner\Service\ScanLogger' ) ) {
			require_once dirname( dirname( __DIR__ ) ) . '/Service/ScanLogger.php';
		}
		\SecurWP\Modules\Scanner\Service\ScanLogger::log( 'Publishing final scan results...' );
		ScanQueue::complete();

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

	/**
	 * Surface poison jobs in the final report.
	 *
	 * @param string $scan_id
	 * @return void
	 */
	private function stage_dead_task_issues( string $scan_id, array $dead_tasks ): void {
		if ( ! class_exists( IssueRepository::class ) ) {
			require_once dirname( __DIR__, 2 ) . '/Repository/IssueRepository.php';
		}

		foreach ( $dead_tasks as $dead_task ) {
			$task_type = sanitize_key( (string) ( $dead_task['task_type'] ?? 'task' ) );
			$error_message = sanitize_text_field( (string) ( $dead_task['result']['error'] ?? 'Task failed repeatedly' ) );
			$hash = IssueRepository::generateHash( 'system_error', 'task:' . $task_type . ':' . (int) ( $dead_task['id'] ?? 0 ) );

			IssueRepository::stage(
				[
					'scan_id'  => $scan_id,
					'hash'     => $hash,
					'type'     => 'system_error',
					'status'   => 'failed',
					'severity' => 'high',
					'message'  => sprintf( 'Background task "%s" failed repeatedly: %s', $task_type, $error_message ),
					'file'     => '(scan)',
					'data'     => [
						'source'      => 'task_queue_finalize',
						'task_type'   => $task_type,
						'task_id'     => (int) ( $dead_task['id'] ?? 0 ),
						'attempts'    => (int) ( $dead_task['attempts'] ?? 0 ),
						'error_code'  => 'task_dead_letter',
					],
				]
			);
		}
	}
}
