<?php
/**
 * WooCommerce product image integration.
 *
 * @package AIAltTextGenerator
 * @since 1.5.0
 */

namespace AIAltTextGenerator;

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

/**
 * @since 1.5.0
 */
class WooCommerceIntegration {

	public function register(): void {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return;
		}

		add_action( 'add_meta_boxes', [ $this, 'addProductMetaBox' ] );
		add_action( 'wp_ajax_wpps_ai_alt_product_generate', [ $this, 'ajaxGenerateProductImages' ] );
	}

	public function addProductMetaBox(): void {
		add_meta_box(
			'wpps-ai-alt-product',
			__( 'AI Alt Text — Product Images', 'wp-powersuite' ),
			[ $this, 'renderProductMetaBox' ],
			'product',
			'side',
			'default'
		);
	}

	public function renderProductMetaBox( \WP_Post $post ): void {
		if ( ! Capabilities::canGenerate() ) {
			echo '<p class="description">' . esc_html__( 'You do not have permission to generate alt text.', 'wp-powersuite' ) . '</p>';
			return;
		}

		$images = self::getProductImageIds( (int) $post->ID );
		if ( $images === [] ) {
			echo '<p class="description">' . esc_html__( 'No product images found.', 'wp-powersuite' ) . '</p>';
			return;
		}

		echo '<ul class="wpps-ai-alt-product-list">';
		foreach ( $images as $image ) {
			$status = AttachmentStatus::resolve( $image['id'] );
			printf(
				'<li><strong>%1$s</strong><br><span class="wpps-ai-alt-badge %2$s">%3$s</span></li>',
				esc_html( $image['label'] ),
				esc_attr( AttachmentStatus::badgeClass( $status['slug'] ) ),
				esc_html( $status['label'] )
			);
		}
		echo '</ul>';

		printf(
			'<p><button type="button" class="button button-primary" id="wpps-ai-alt-product-generate" data-product-id="%1$d">%2$s</button></p>',
			(int) $post->ID,
			esc_html__( 'Generate all product images', 'wp-powersuite' )
		);
	}

	public function ajaxGenerateProductImages(): void {
		if ( ! check_ajax_referer( Module::nonceAction(), 'nonce', false ) || ! Capabilities::canGenerate() ) {
			wp_send_json_error( [ 'message' => __( 'Permission denied.', 'wp-powersuite' ) ] );
		}

		$product_id = isset( $_POST['product_id'] ) ? (int) $_POST['product_id'] : 0;
		if ( $product_id <= 0 || ! current_user_can( 'edit_post', $product_id ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid product.', 'wp-powersuite' ) ] );
		}

		if ( ! Settings::hasApiKey() ) {
			wp_send_json_error( [ 'message' => __( 'API key not configured.', 'wp-powersuite' ) ] );
		}

		$images  = self::getProductImageIds( $product_id );
		$ids     = array_column( $images, 'id' );
		$settings = Settings::get();

		if ( ! empty( $settings['queue_enabled'] ) ) {
			$added = Queue::enqueue( $ids );
			wp_send_json_success( [
				'queued'  => $added,
				'message' => sprintf(
					/* translators: 1: number, 2: number. */
					_n( '%d product image queued.', '%d product images queued.', $added, 'wp-powersuite' ),
					$added
				),
			] );
		}

		$ok = 0;
		$fail = 0;
		foreach ( $ids as $attachment_id ) {
			if ( ! Module::checkRateLimit() ) {
				++$fail;
				continue;
			}
			$result = GenerationService::generateForAttachment( $attachment_id );
			if ( $result['status'] === 'success' ) {
				++$ok;
			} else {
				++$fail;
			}
		}

		wp_send_json_success( [
			'processed' => $ok,
			'failed'    => $fail,
			'message'   => sprintf(
				/* translators: 1: number, 2: number. */
				__( 'Generated alt text for %1$d images. %2$d failed or skipped.', 'wp-powersuite' ),
				$ok,
				$fail
			),
		] );
	}

	/**
	 * @return list<array{id: int, label: string, type: string}>
	 */
	public static function getProductImageIds( int $product_id ): array {
		$images = [];

		$thumb = (int) get_post_thumbnail_id( $product_id );
		if ( $thumb > 0 ) {
			$images[] = [
				'id'    => $thumb,
				'label' => __( 'Featured image', 'wp-powersuite' ),
				'type'  => 'featured',
			];
		}

		$gallery = array_filter( array_map( 'intval', explode( ',', (string) get_post_meta( $product_id, '_product_image_gallery', true ) ) ) );
		foreach ( $gallery as $index => $attachment_id ) {
			$images[] = [
				'id'    => $attachment_id,
				/* translators: %d: number value. */
				'label' => sprintf( __( 'Gallery image %d', 'wp-powersuite' ), $index + 1 ),
				'type'  => 'gallery',
			];
		}

		$variations = get_posts(
			[
				'post_type'      => 'product_variation',
				'post_parent'    => $product_id,
				'post_status'    => [ 'publish', 'private' ],
				'posts_per_page' => -1,
				'fields'         => 'ids',
			]
		);

		foreach ( $variations as $variation_id ) {
			$variation_id = (int) $variation_id;
			$image_id     = (int) get_post_meta( $variation_id, '_thumbnail_id', true );
			if ( $image_id <= 0 ) {
				continue;
			}

			$label = (string) $variation_id;
			if ( function_exists( 'wc_get_product' ) ) {
				$variation = wc_get_product( $variation_id );
				if ( $variation && $variation->is_type( 'variation' ) ) {
					$attrs = $variation->get_variation_attributes();
					if ( is_array( $attrs ) && $attrs !== [] ) {
						$label = implode( ' / ', array_filter( array_map( 'strval', $attrs ) ) );
					}
				}
			}

			$images[] = [
				'id'    => $image_id,
				/* translators: %s: string value. */
				'label' => sprintf( __( 'Variation: %s', 'wp-powersuite' ), $label ),
				'type'  => 'variation',
			];
		}

		$seen = [];
		$unique = [];
		foreach ( $images as $image ) {
			if ( isset( $seen[ $image['id'] ] ) ) {
				continue;
			}
			$seen[ $image['id'] ] = true;
			$unique[] = $image;
		}

		return $unique;
	}

	/**
	 * Count product images missing alt text.
	 */
	public static function countMissingProductImages(): int {
		if ( ! class_exists( 'WooCommerce' ) ) {
			return 0;
		}

		$products = get_posts(
			[
				'post_type'      => 'product',
				'post_status'    => 'publish',
				'posts_per_page' => 200,
				'fields'         => 'ids',
			]
		);

		$missing = 0;
		foreach ( $products as $product_id ) {
			foreach ( self::getProductImageIds( (int) $product_id ) as $image ) {
				$alt = (string) get_post_meta( $image['id'], '_wp_attachment_image_alt', true );
				if ( $alt === '' && ! AttachmentMeta::isDecorative( $image['id'] ) ) {
					++$missing;
				}
			}
		}

		return $missing;
	}
}

