<?php
/**
 * Donations List Block
 *
 * Provides a block to display all donations with donor name, date, and public message.
 * Displays donations from the current fundraiser and all its children recursively.
 *
 * @package AmbassadorHub\Fundraisers\Blocks\DonationsList
 */

namespace AmbassadorHub\Fundraisers\Blocks\DonationsList;

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

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare

use AmbassadorHub\Donations\DonationsModule;
use AmbassadorHub\Donors\DonorsModule;
use AmbassadorHub\Fundraisers\Admin\Settings\SettingsManager;
use AmbassadorHub\Fundraisers\FundraisersModule;

/**
 * Donations List block registration and rendering.
 */
final class Block {
	/**
	 * Initialize the block.
	 *
	 * @return void
	 */
	public static function init(): void {
		add_action( 'init', array( self::class, 'register_block' ) );
	}

	/**
	 * Register the block.
	 *
	 * @return void
	 */
	public static function register_block(): void {
		// Register editor script.
		$handle    = 'ambh-donations-list-block';
		$block_dir = AMBASSADOR_HUB_PATH . 'src/Fundraisers/Blocks/DonationsList/';
		$block_url = AMBASSADOR_HUB_URL . 'src/Fundraisers/Blocks/DonationsList/';

		// Only register script if the file exists.
		$script_file = $block_dir . 'index.js';
		if ( file_exists( $script_file ) ) {
			wp_register_script(
				$handle,
				$block_url . 'index.js',
				array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-server-side-render' ),
				filemtime( $script_file ),
				true
			);
		}

		// Register frontend styles.
		wp_register_style(
			'ambh-donations-list',
			$block_url . 'style.css',
			array(),
			AMBASSADOR_HUB_VERSION
		);

		$block_args = array(
			'style'           => 'ambh-donations-list',
			'render_callback' => array( self::class, 'render_block' ),
		);

		// Only include editor script if it was registered.
		if ( file_exists( $script_file ) ) {
			$block_args['editor_script'] = $handle;
		}

		register_block_type( $block_dir, $block_args );

		// Register shortcode alias.
		add_shortcode( 'ambh_donations_list', array( self::class, 'render_shortcode' ) );
	}

	/**
	 * Render the block.
	 *
	 * @param array $attributes Block attributes.
	 *
	 * @return string Block HTML.
	 */
	public static function render_block( array $attributes = array() ): string {
		global $post;

		// Get limit from attributes or use default.
		$limit = isset( $attributes['limit'] ) && $attributes['limit'] > 0
			? intval( $attributes['limit'] )
			: 10;

		// Get fundraiser ID from current post context.
		$fundraiser_id = isset( $post->ID ) && FundraisersModule::POST_TYPE === get_post_type( $post )
			? $post->ID
			: 0;

		// If no fundraiser context, show nothing.
		if ( 0 === $fundraiser_id ) {
			if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
				return '<div style="padding: 20px; background: #f0f0f1; border: 1px solid #ddd; text-align: center;">'
					. esc_html__( 'Fundraiser Donatie lijst.', 'ambassadorhub' )
					. '</div>';
			}
			return '';
		}

		// Get donations from this fundraiser and all children.
		$donations = self::get_donations( $fundraiser_id, $limit );

		if ( empty( $donations ) ) {
			// Return a message if in editor context, empty if on frontend.
			if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
				return '<div style="padding: 20px; background: #f0f0f1; border: 1px solid #ddd; text-align: center;">'
					. esc_html__( 'Geen donaties gevonden.', 'ambassadorhub' )
					. '</div>';
			}
			return '';
		}

		ob_start();
		?>
		<div class="donations-list-block">
			<div class="donations-list">
				<?php foreach ( $donations as $donation ) : ?>
					<div class="donation-item">
						<div class="donation-header">
							<span class="donor-name">
								<?php
								$display_name = DonationsModule::get_donor_name_for_display( $donation );
								echo esc_html( $display_name );
								?>
								<?php if ( $donation->fundraiser_id !== $fundraiser_id ) : ?>
									<?php
									$owner_id = (int) get_post_field( 'post_author', $donation->fundraiser_id );
									if ( $owner_id ) {
										$owner = get_user_by( 'ID', $owner_id );
										if ( $owner ) {
											echo ' <span class="child-fundraiser-organiser"> aan ' . esc_html( $owner->display_name ) . '</span>';
										}
									}
									?>
								<?php endif; ?>
							</span>
							<span class="donation-date"><?php echo esc_html( date_i18n( get_option( 'date_format' ), strtotime( $donation->created_at ) ) ); ?></span>
						</div>
						<?php if ( ! empty( $donation->message ) ) : ?>
							<div class="donation-message">
								<?php echo esc_html( $donation->message ); ?>
							</div>
						<?php endif; ?>
						<div class="donation-amount">
						<?php echo esc_html( SettingsManager::format_currency( (float) $donation->amount ) ); ?>
						</div>
					</div>
				<?php endforeach; ?>
			</div>
		</div>
		<?php
		return ob_get_clean();
	}

	/**
	 * Render shortcode.
	 *
	 * @param array $atts Shortcode attributes.
	 *
	 * @return string
	 */
	public static function render_shortcode( $atts ): string {
		global $post;

		$atts = shortcode_atts(
			array(
				'limit'         => 10,
				'fundraiser_id' => isset( $post->ID ) && FundraisersModule::POST_TYPE === get_post_type( $post ) ? $post->ID : 0,
			),
			$atts
		);

		return self::render_block(
			array(
				'limit' => intval( $atts['limit'] ),
			)
		);
	}

	/**
	 * Get all child fundraiser IDs recursively.
	 *
	 * @param int $parent_id Parent fundraiser ID.
	 * @return array Array of fundraiser IDs including parent.
	 */
	private static function get_all_fundraiser_ids( int $parent_id ): array {
		$ids = array( $parent_id );

		// Get direct children.
		$children = get_posts(
			array(
				'post_type'      => FundraisersModule::POST_TYPE,
				'post_parent'    => $parent_id,
				'posts_per_page' => -1,
				'fields'         => 'ids',
				'post_status'    => 'any',
			)
		);

		// Recursively get children of children.
		foreach ( $children as $child_id ) {
			$ids = array_merge( $ids, self::get_all_fundraiser_ids( $child_id ) );
		}

		return $ids;
	}

	/**
	 * Get donations for display.
	 *
	 * @param int $fundraiser_id Fundraiser ID to get donations for (including children).
	 * @param int $limit Number of donations to retrieve.
	 * @return array Array of donation objects.
	 */
	private static function get_donations( int $fundraiser_id, int $limit = 10 ): array {
		global $wpdb;
		$table_name   = DonationsModule::get_table_name();
		$donors_table = DonorsModule::get_table_name();

		// Get all fundraiser IDs recursively.
		$fundraiser_ids = self::get_all_fundraiser_ids( $fundraiser_id );

		// Build placeholders for IN clause.
		$placeholders = implode( ', ', array_fill( 0, count( $fundraiser_ids ), '%d' ) );

		$sql = "SELECT d.*,
		               dn.first_name   AS linked_donor_first_name,
		               dn.last_name    AS linked_donor_last_name,
		               dn.name         AS linked_donor_name,
		               dn.email        AS linked_donor_email,
		               dn.is_anonymous AS linked_donor_is_anonymous
		        FROM {$table_name} d
		        LEFT JOIN {$donors_table} dn ON dn.id = d.donor_id
		        WHERE d.status = 'completed'
		          AND d.fundraiser_id IN ({$placeholders})
		        ORDER BY d.created_at DESC
		        LIMIT %d";

		// Merge fundraiser IDs with limit for prepare.
		$params = array_merge( $fundraiser_ids, array( $limit ) );

		return $wpdb->get_results( $wpdb->prepare( $sql, $params ) );
	}
}
