<?php
/**
 * Detect where attachments are used in site content.
 *
 * @package AIAltTextGenerator
 * @since 1.7.0
 */

namespace AIAltTextGenerator;

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

/**
 * @since 1.7.0
 */
class AttachmentUsage {

	private const CACHE_PREFIX = 'wpps_ai_alt_usage_';
	private const CACHE_TTL    = 1800;

	/**
	 * @return list<int>
	 */
	public static function findPostIds( int $attachment_id, int $limit = 10 ): array {
		$cache_key = self::CACHE_PREFIX . $attachment_id;
		$cached    = get_transient( $cache_key );
		if ( is_array( $cached ) ) {
			return array_slice( array_map( 'intval', $cached ), 0, $limit );
		}

		global $wpdb;

		$ids = [];

		$featured = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_thumbnail_id' AND meta_value = %s",
				$attachment_id
			)
		);
		$ids = array_merge( $ids, array_map( 'intval', $featured ?: [] ) );

		$like_patterns = [
			'%wp-image-' . $attachment_id . '%',
			'%"id":' . $attachment_id . '%',
			'%"id":"' . $attachment_id . '"%',
		];

		$url = (string) wp_get_attachment_url( $attachment_id );
		if ( $url !== '' ) {
			$like_patterns[] = '%' . $wpdb->esc_like( $url ) . '%';
		}

		foreach ( $like_patterns as $pattern ) {
			$found = $wpdb->get_col(
				$wpdb->prepare(
					"SELECT ID FROM {$wpdb->posts}
					WHERE post_status IN ('publish','draft','pending','future','private')
					AND post_type NOT IN ('attachment','revision','nav_menu_item')
					AND (post_content LIKE %s OR post_excerpt LIKE %s)
					LIMIT 50",
					$pattern,
					$pattern
				)
			);
			$ids = array_merge( $ids, array_map( 'intval', $found ?: [] ) );
		}

		$elementor = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT post_id FROM {$wpdb->postmeta}
				WHERE meta_key = '_elementor_data'
				AND (meta_value LIKE %s OR meta_value LIKE %s)
				LIMIT 50",
				'%"id":' . $attachment_id . '%',
				'%"id":"' . $attachment_id . '"%'
			)
		);
		$ids = array_merge( $ids, array_map( 'intval', $elementor ?: [] ) );

		$ids = array_values( array_unique( array_filter( $ids ) ) );
		set_transient( $cache_key, $ids, self::CACHE_TTL );

		return array_slice( $ids, 0, $limit );
	}

	public static function countPosts( int $attachment_id ): int {
		$cache_key = self::CACHE_PREFIX . $attachment_id;
		$cached    = get_transient( $cache_key );
		if ( is_array( $cached ) ) {
			return count( $cached );
		}

		return count( self::findPostIds( $attachment_id, 50 ) );
	}

	/**
	 * Render-friendly summary for admin columns.
	 */
	public static function getColumnSummary( int $attachment_id, int $limit = 3 ): string {
		$post_ids = self::findPostIds( $attachment_id, $limit );
		if ( $post_ids === [] ) {
			return '';
		}

		$labels = [];
		foreach ( $post_ids as $post_id ) {
			$title = get_the_title( $post_id );
			$link  = get_edit_post_link( $post_id, 'raw' );
			$text  = $title !== '' ? $title : '#' . $post_id;
			$labels[] = $link
				? '<a href="' . esc_url( $link ) . '">' . esc_html( $text ) . '</a>'
				: esc_html( $text );
		}

		$total = self::countPosts( $attachment_id );
		if ( $total > $limit ) {
			$labels[] = sprintf(
				/* translators: %d: additional post count */
				esc_html__( '+%d more', 'wp-powersuite' ),
				$total - $limit
			);
		}

		return implode( '<br>', $labels );
	}

	public static function invalidateCache( int $attachment_id ): void {
		delete_transient( self::CACHE_PREFIX . $attachment_id );
	}

	/**
	 * Invalidate usage cache for attachments referenced in a saved post.
	 */
	public static function invalidateForPost( int $post_id ): void {
		$post = get_post( $post_id );
		if ( ! $post instanceof \WP_Post || $post->post_type === 'attachment' ) {
			return;
		}

		$ids = self::extractAttachmentIdsFromPost( $post );
		foreach ( $ids as $attachment_id ) {
			self::invalidateCache( $attachment_id );
		}
	}

	/** @return list<int> */
	private static function extractAttachmentIdsFromPost( \WP_Post $post ): array {
		$ids = [];

		if ( has_blocks( $post->post_content ) ) {
			$ids = array_merge( $ids, self::extractIdsFromBlocks( parse_blocks( $post->post_content ) ) );
		}

		if ( preg_match_all( '/\bwp-image-(\d+)\b/i', $post->post_content, $matches ) ) {
			foreach ( $matches[1] as $id ) {
				$ids[] = (int) $id;
			}
		}

		$thumb = (int) get_post_thumbnail_id( $post->ID );
		if ( $thumb > 0 ) {
			$ids[] = $thumb;
		}

		return array_values( array_unique( array_filter( $ids ) ) );
	}

	/**
	 * @param list<array<string, mixed>> $blocks
	 * @return list<int>
	 */
	private static function extractIdsFromBlocks( array $blocks ): array {
		$ids = [];
		foreach ( $blocks as $block ) {
			if ( ! is_array( $block ) ) {
				continue;
			}
			$attrs = is_array( $block['attrs'] ?? null ) ? $block['attrs'] : [];
			$id    = (int) ( $attrs['id'] ?? 0 );
			if ( $id > 0 ) {
				$ids[] = $id;
			}
			if ( ! empty( $attrs['ids'] ) && is_array( $attrs['ids'] ) ) {
				foreach ( $attrs['ids'] as $gallery_id ) {
					$gallery_id = (int) $gallery_id;
					if ( $gallery_id > 0 ) {
						$ids[] = $gallery_id;
					}
				}
			}
			if ( ! empty( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) ) {
				$ids = array_merge( $ids, self::extractIdsFromBlocks( $block['innerBlocks'] ) );
			}
		}

		return $ids;
	}
}
