<?php
/**
 * Runtime diagnostics for AI Alt Text.
 *
 * @package AIAltTextGenerator
 * @since 2.4.2
 */

namespace AIAltTextGenerator;

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

/**
 * Collects environment and module health details for the settings UI.
 *
 * @since 2.4.2
 */
class Diagnostics {

	public const LAST_ERROR_OPTION = 'wpps_ai_alt_last_bulk_error';

	/**
	 * @return array<string, mixed>
	 */
	public static function report(): array {
		$settings = Settings::get();
		$provider = (string) ( $settings['provider'] ?? 'openai' );
		$model    = (string) ( $settings['model'] ?? Models::DEFAULT );
		$queue    = Queue::getStatus();
		$uploads  = wp_upload_dir();

		return [
			'wordpress'            => get_bloginfo( 'version' ),
			'php'                  => PHP_VERSION,
			'memory_limit'         => (string) ini_get( 'memory_limit' ),
			'max_execution_time'   => (string) ini_get( 'max_execution_time' ),
			'provider'             => $provider,
			'model'                => $model,
			'has_api_key'          => Settings::hasApiKey( $provider ),
			'queue_enabled'        => ! empty( $settings['queue_enabled'] ),
			'queue_status'         => (string) ( $queue['status'] ?? 'idle' ),
			'cron_disabled'        => defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON,
			'next_queue_cron'      => wp_next_scheduled( Queue::CRON_HOOK ),
			'uploads_writable'     => empty( $uploads['error'] ),
			'uploads_basedir'      => (string) ( $uploads['basedir'] ?? '' ),
			'remote_get_blocked'   => (bool) apply_filters( 'http_request_host_is_external', false, 'api.openai.com', 443 ),
			'gd_loaded'            => extension_loaded( 'gd' ),
			'imagick_loaded'       => extension_loaded( 'imagick' ),
			'action_scheduler'     => class_exists( 'ActionScheduler' ),
			'last_bulk_error'      => self::getLastBulkError(),
			'debug_logging'        => ! empty( $settings['debug_logging'] ),
		];
	}

	/**
	 * @param array<string, mixed> $error
	 */
	public static function recordBulkError( array $error ): void {
		update_option(
			self::LAST_ERROR_OPTION,
			[
				'code'          => sanitize_key( (string) ( $error['code'] ?? '' ) ),
				'message'       => sanitize_text_field( (string) ( $error['message'] ?? '' ) ),
				'attachment_id' => (int) ( $error['attachment_id'] ?? 0 ),
				'time'          => time(),
			],
			false
		);
	}

	/**
	 * @return array<string, mixed>|null
	 */
	public static function getLastBulkError(): ?array {
		$raw = get_option( self::LAST_ERROR_OPTION, null );
		if ( ! is_array( $raw ) ) {
			return null;
		}

		return [
			'code'          => (string) ( $raw['code'] ?? '' ),
			'message'       => (string) ( $raw['message'] ?? '' ),
			'attachment_id' => (int) ( $raw['attachment_id'] ?? 0 ),
			'time'          => (int) ( $raw['time'] ?? 0 ),
		];
	}

	/**
	 * Structured debug log when enabled in settings.
	 *
	 * @param array<string, mixed> $context
	 */
	public static function debug( string $stage, array $context = [] ): void {
		$settings = Settings::get();
		if ( empty( $settings['debug_logging'] ) ) {
			return;
		}

		$safe = $context;
		unset( $safe['api_key'], $safe['authorization'], $safe['image_data'], $safe['base64'] );

		if ( isset( $safe['message'] ) && is_string( $safe['message'] ) ) {
			$safe['message'] = substr( $safe['message'], 0, 500 );
		}

		Logger::log(
			[
				'attachment_id' => (int) ( $safe['attachment_id'] ?? 0 ),
				'filename'      => (string) ( $safe['filename'] ?? '' ),
				'old_alt'       => '',
				'new_alt'       => '',
				'provider'      => (string) ( $safe['provider'] ?? ( $settings['provider'] ?? '' ) ),
				'model'         => (string) ( $safe['model'] ?? ( $settings['model'] ?? '' ) ),
				'status'        => 'debug',
				'error_message' => wp_json_encode(
					[
						'stage'   => $stage,
						'context' => $safe,
					]
				),
				'tokens_used'   => 0,
			]
		);
	}
}
