<?php
/**
 * Campaign List Table Columns
 *
 * @package AmbassadorHub\Campaigns\Admin
 */

namespace AmbassadorHub\Campaigns\Admin;

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

use AmbassadorHub\Admin\InlineAssets;
use AmbassadorHub\Admin\StatsListTableActions;
use AmbassadorHub\Campaigns\CampaignsModule;
use AmbassadorHub\Fundraisers\Admin\Settings\SettingsManager;
use AmbassadorHub\Fundraisers\FundraisersModule;

/**
 * Registers and renders custom columns on the campaign list table.
 */
final class ListTable {

	/**
	 * Initialize list-table column hooks.
	 *
	 * @return void
	 */
	public static function init(): void {
		add_filter( 'manage_' . CampaignsModule::POST_TYPE . '_posts_columns', array( self::class, 'add_campaign_custom_columns' ) );
		add_action( 'manage_' . CampaignsModule::POST_TYPE . '_posts_custom_column', array( self::class, 'render_campaign_custom_columns' ), 10, 2 );
		add_filter( 'manage_edit-' . CampaignsModule::POST_TYPE . '_sortable_columns', array( self::class, 'add_sortable_columns' ) );
		add_filter( 'display_post_states', array( self::class, 'add_ended_state' ), 10, 2 );
		add_action( 'admin_footer-post.php', array( self::class, 'fix_ended_status_publish_metabox' ) );

		StatsListTableActions::init(
			CampaignsModule::POST_TYPE,
			CampaignsModule::STATS_PAGE_SLUG,
			'post_row_actions'
		);
	}

	/**
	 * Add custom columns to the campaign list table.
	 *
	 * @param array $columns Existing columns.
	 * @return array Modified columns.
	 */
	public static function add_campaign_custom_columns( array $columns ): array {
		$new_columns = array();
		foreach ( $columns as $key => $value ) {
			$new_columns[ $key ] = $value;
			if ( 'title' === $key ) {
				$new_columns['fundraisers_count'] = __( 'Fundraisers', 'ambassadorhub' );
				$new_columns['total_raised']      = __( 'Total Raised', 'ambassadorhub' );
				$new_columns['financial_goal']    = __( 'Goal', 'ambassadorhub' );
			}
			if ( 'date' === $key ) {
				$new_columns['end_date'] = __( 'End Date', 'ambassadorhub' );
			}
		}
		return $new_columns;
	}

	/**
	 * Render custom column values for the campaign list table.
	 *
	 * @param string $column  Column slug.
	 * @param int    $post_id Post ID.
	 * @return void
	 */
	public static function render_campaign_custom_columns( string $column, int $post_id ): void {
		global $wpdb;

		if ( 'fundraisers_count' === $column ) {
			$count = get_posts(
				array(
					'post_type'      => FundraisersModule::POST_TYPE,
					'posts_per_page' => -1,
					'meta_key'       => '_ambh_campaign_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- required for campaign fundraiser count.
				'meta_value'         => $post_id, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
				'fields'             => 'ids',
				)
			);
			echo (int) count( $count );
			return;
		}

		if ( 'end_date' === $column ) {
			$end_date = get_post_meta( $post_id, '_ambh_end_date', true );
			echo $end_date ? esc_html( wp_date( get_option( 'date_format' ), strtotime( $end_date ) ) ) : '—';
			return;
		}

		if ( 'financial_goal' === $column ) {
			$goal = (float) get_post_meta( $post_id, '_ambh_financial_goal', true );
			echo $goal > 0 ? esc_html( SettingsManager::format_currency( $goal ) ) : '—';
			return;
		}

		if ( 'total_raised' === $column ) {
			$fundraiser_ids = get_posts(
				array(
					'post_type'      => FundraisersModule::POST_TYPE,
					'posts_per_page' => -1,
					'meta_key'       => '_ambh_campaign_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- required for campaign total raised calculation.
				'meta_value'         => $post_id, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
				'fields'             => 'ids',
				)
			);

			if ( empty( $fundraiser_ids ) ) {
				echo esc_html( SettingsManager::format_currency( 0 ) );
				return;
			}

			$table_name   = $wpdb->prefix . 'ambh_donations';
			$placeholders = implode( ',', array_fill( 0, count( $fundraiser_ids ), '%d' ) );

			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- $table_name is built from $wpdb->prefix (safe); $placeholders contains only literal %d tokens that are expanded at runtime via spread operator (safe); no appropriate cache key for this aggregate.
			$total = $wpdb->get_var( $wpdb->prepare( "SELECT COALESCE(SUM(amount), 0) FROM {$table_name} WHERE fundraiser_id IN ({$placeholders}) AND status = 'completed'", ...$fundraiser_ids ) );

			echo esc_html( SettingsManager::format_currency( (float) $total ) );
		}
	}

	/**
	 * Make custom columns sortable.
	 *
	 * @param array<string,string> $columns Sortable columns.
	 *
	 * @return array<string,string> Modified sortable columns.
	 */
	public static function add_sortable_columns( array $columns ): array {
		$columns['end_date'] = 'end_date';
		return $columns;
	}

	/**
	 * Append an "Ended" post state badge to campaign titles in the list table.
	 *
	 * @param string[]  $post_states Existing post state labels.
	 * @param \WP_Post  $post        Current post object.
	 * @return string[] Modified post states.
	 */
	public static function add_ended_state( array $post_states, \WP_Post $post ): array {
		if ( CampaignsModule::POST_TYPE === $post->post_type && 'ended' === $post->post_status ) {
			$post_states['ended'] = __( 'Ended', 'ambassadorhub' );
		}
		return $post_states;
	}

	/**
	 * Inject the "Ended" option into the Publish metabox status dropdown.
	 *
	 * WordPress's Publish metabox only knows built-in statuses, so a custom
	 * "ended" post renders no label. This script adds the option and updates
	 * the display text so the metabox shows "Ended" correctly.
	 */
	public static function fix_ended_status_publish_metabox(): void {
		global $post;
		if ( ! $post || CampaignsModule::POST_TYPE !== $post->post_type || 'ended' !== $post->post_status ) {
			return;
		}
		$label = __( 'Ended', 'ambassadorhub' );

		InlineAssets::script(
			'jQuery( function( $ ) {
			$( \'#post-status-display\' ).text( \'' . esc_js( $label ) . '\' );
			$( \'#post_status\' ).append( \'<option value="ended" selected="selected">' . esc_js( $label ) . '</option>\' );
		} );'
		);
	}
}
