<?php
/**
 * Campaign Stats / Detail Meta Boxes
 *
 * Registers the meta boxes shown on the campaign stats/detail page.
 * The fundraisers list rendering is delegated to Fundraisers\Admin\MetaBoxes
 * so the edit screen keeps only editable fields.
 *
 * @package AmbassadorHub\Campaigns\Admin
 */

namespace AmbassadorHub\Campaigns\Admin;

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

use AmbassadorHub\Admin\Charts\ChartRenderer;
use AmbassadorHub\Admin\InlineAssets;
use AmbassadorHub\Campaigns\CampaignsModule;
use AmbassadorHub\Donations\DonationsModule;
use AmbassadorHub\Fundraisers\Admin\Settings\SettingsManager;
use AmbassadorHub\Fundraisers\FundraisersModule;

/**
 * Registers and renders meta boxes shown on the campaign detail/stats page.
 */
final class Stats {

	/**
	 * Initialize stats meta box hooks.
	 *
	 * @return void
	 */
	public static function init(): void {
		add_action( 'add_meta_boxes', array( self::class, 'register_stat_metaboxes' ) );
		add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_assets' ) );
	}

	/**
	 * Enqueue the statistics meta box CSS for the campaign detail/stats page.
	 *
	 * Hooked from admin_enqueue_scripts, which fires early enough for
	 * wp_add_inline_style() to still be picked up by admin_print_styles.
	 *
	 * @return void
	 */
	public static function enqueue_assets(): void {
		// @phpstan-ignore-next-line
		$page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only GET parameter for stats page routing.
		if ( CampaignsModule::STATS_PAGE_SLUG !== $page ) {
			return;
		}

		InlineAssets::style(
			'#ambh_campaign_statistics .ambh-dashboard__section { background: transparent; border: none; padding: 0; margin: 0; }
			#ambh_campaign_statistics .ambh-dashboard__section-title { display: none; }
			#ambh_campaign_statistics .ambh-dashboard__graph { height: 420px; }'
		);
	}

	/**
	 * Register meta boxes for the campaign stats/detail page.
	 *
	 * Only fires when the `page` query var matches the campaign stats slug, so
	 * none of these boxes appear on the standard edit screen.
	 *
	 * @return void
	 */
	public static function register_stat_metaboxes(): void {
		// @phpstan-ignore-next-line
		$page            = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only GET parameter for stats page routing.
		$stats_page_slug = CampaignsModule::STATS_PAGE_SLUG;

		if ( ! $page || $stats_page_slug !== $page ) {
			return;
		}

		// @phpstan-ignore-next-line
		$post_id = isset( $_GET['post_id'] ) ? (int) $_GET['post_id'] : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only GET parameter for stats display.
		if ( ! $post_id ) {
			return;
		}

		$screen    = get_current_screen();
		$screen_id = $screen ? $screen->id : $stats_page_slug;

		// Statistics (KPIs + chart) — totals across all fundraisers in this campaign.
		add_meta_box(
			'ambh_campaign_statistics',
			__( 'Statistics', 'ambassadorhub' ),
			array( self::class, 'render_statistics_metabox' ),
			$screen_id,
			'normal',
			'high'
		);

		// Fundraisers list (read-only) — rendering delegated to Fundraisers MetaBoxes.
		add_meta_box(
			'campaign_fundraisers',
			__( 'Fundraisers', 'ambassadorhub' ),
			array( \AmbassadorHub\Fundraisers\Admin\MetaBoxes::class, 'render_campaign_fundraisers_meta_box' ),
			$screen_id,
			'normal',
			'default'
		);
	}

	// -------------------------------------------------------------------------
	// Statistics meta box
	// -------------------------------------------------------------------------

	/**
	 * Render the campaign statistics meta box (KPIs + chart across all fundraisers).
	 *
	 * @param \WP_Post $post Current campaign post.
	 * @return void
	 */
	public static function render_statistics_metabox( \WP_Post $post ): void {
		$kpis       = self::get_campaign_kpi_data( $post->ID );
		$chart_data = self::get_campaign_chart_data( $post->ID );
		?>
		<div class="ambh-kpi-grid" style="margin-bottom: 20px;">
			<div class="ambh-kpi-card">
				<span class="ambh-kpi-card__icon dashicons dashicons-clipboard"></span>
				<div class="ambh-kpi-card__body">
					<span class="ambh-kpi-card__value"><?php echo esc_html( number_format_i18n( $kpis['count'] ) ); ?></span>
					<span class="ambh-kpi-card__label"><?php esc_html_e( 'Number of donations', 'ambassadorhub' ); ?></span>
				</div>
			</div>
			<div class="ambh-kpi-card">
				<span class="ambh-kpi-card__icon dashicons dashicons-chart-bar"></span>
				<div class="ambh-kpi-card__body">
					<span class="ambh-kpi-card__value"><?php echo esc_html( SettingsManager::format_currency( $kpis['average'] ) ); ?></span>
					<span class="ambh-kpi-card__label"><?php esc_html_e( 'Average donation', 'ambassadorhub' ); ?></span>
				</div>
			</div>
			<div class="ambh-kpi-card">
				<span class="ambh-kpi-card__icon dashicons dashicons-money-alt"></span>
				<div class="ambh-kpi-card__body">
					<span class="ambh-kpi-card__value"><?php echo esc_html( SettingsManager::format_currency( $kpis['total'] ) ); ?></span>
					<span class="ambh-kpi-card__label"><?php esc_html_e( 'Total donated', 'ambassadorhub' ); ?></span>
				</div>
			</div>
		</div>

		<?php
		$campaign_goal  = self::get_campaign_goal( $post->ID );
		$progress_pct   = ( $campaign_goal > 0 ) ? min( 100.0, ( $kpis['total'] / $campaign_goal ) * 100 ) : 0.0;
		$end_date       = get_post_meta( $post->ID, '_ambh_end_date', true );
		$days_remaining = ( $end_date ) ? (int) ceil( ( strtotime( $end_date ) - time() ) / DAY_IN_SECONDS ) : null;
		$is_closed      = ( 'ended' === $post->post_status );
		?>

		<div style="display: grid; grid-template-columns: 1fr auto; gap: 16px; align-items: stretch; margin-bottom: 24px;">

			<div style="background: #fff; border: 1px solid <?php echo $progress_pct >= 100 ? '#f0b429' : '#c3c4c7'; ?>; border-radius: 4px; padding: 16px; <?php echo $progress_pct >= 100 ? 'background: linear-gradient(135deg,#fffbea 0%,#fff 100%);' : ''; ?>">
				<div style="display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 13px;">
					<span><?php echo esc_html( SettingsManager::format_currency( $kpis['total'] ) . ' ' . __( 'raised', 'ambassadorhub' ) ); ?></span>
					<span><?php echo esc_html( __( 'Goal:', 'ambassadorhub' ) . ' ' . ( $campaign_goal > 0 ? SettingsManager::format_currency( $campaign_goal ) : '—' ) ); ?></span>
				</div>
				<?php if ( $progress_pct >= 100 ) : ?>
				<div style="background: #f5e6c0; border-radius: 4px; height: 20px; overflow: hidden;">
					<div style="background: linear-gradient(90deg,#f6d365 0%,#fda085 50%,#f6d365 100%); height: 100%; width: 100%;"></div>
				</div>
				<p style="margin: 8px 0 0; font-size: 12px; color: #8a5f00; font-weight: 600;">
					<span class="dashicons dashicons-star-filled" style="font-size: 14px; width: 14px; height: 14px; vertical-align: middle; color: #f0b429;"></span>
					<?php esc_html_e( 'Goal reached!', 'ambassadorhub' ); ?>
				</p>
				<?php else : ?>
				<div style="background: #e0e0e0; border-radius: 4px; height: 16px; overflow: hidden;">
					<div style="background: #0073aa; height: 100%; width: <?php echo esc_attr( number_format( $progress_pct, 2 ) ); ?>%; transition: width 0.3s ease;"></div>
				</div>
					<?php if ( $campaign_goal > 0 ) : ?>
				<p style="margin: 8px 0 0; font-size: 12px; color: #666;"><?php echo esc_html( number_format( $progress_pct, 1 ) . '% ' . __( 'of goal reached', 'ambassadorhub' ) ); ?></p>
				<?php endif; ?>
				<?php endif; ?>
			</div>

			<div class="ambh-kpi-card" style="height: 100%; box-sizing: border-box;<?php echo $is_closed ? ' background: #f6f7f7; border-color: #dcdcde; opacity: 0.55;' : ''; ?>">
				<span class="ambh-kpi-card__icon dashicons dashicons-calendar-alt"></span>
				<div class="ambh-kpi-card__body">
					<?php if ( $is_closed ) : ?>
						<span class="ambh-kpi-card__value">0</span>
						<span class="ambh-kpi-card__label"><?php esc_html_e( 'Closed', 'ambassadorhub' ); ?></span>
					<?php elseif ( null === $days_remaining ) : ?>
						<span class="ambh-kpi-card__value">—</span>
						<span class="ambh-kpi-card__label"><?php esc_html_e( 'No end date set', 'ambassadorhub' ); ?></span>
					<?php elseif ( $days_remaining <= 0 ) : ?>
						<span class="ambh-kpi-card__value"><?php esc_html_e( 'Ended', 'ambassadorhub' ); ?></span>
						<span class="ambh-kpi-card__label"><?php esc_html_e( 'Campaign ended', 'ambassadorhub' ); ?></span>
					<?php else : ?>
						<span class="ambh-kpi-card__value"><?php echo esc_html( (string) $days_remaining ); ?></span>
						<span class="ambh-kpi-card__label"><?php esc_html_e( 'Days remaining', 'ambassadorhub' ); ?></span>
					<?php endif; ?>
				</div>
			</div>

		</div>

		<?php if ( 0 === $kpis['count'] ) : ?>
			<p style="margin: 8px 0;"><?php esc_html_e( 'No completed donations yet.', 'ambassadorhub' ); ?></p>
		<?php else : ?>
			<?php
			ChartRenderer::render(
				__( 'Campaign Statistics', 'ambassadorhub' ),
				'ambh-campaign-chart-' . $post->ID,
				array(
					'type'    => 'bar',
					'data'    => array(
						'labels'   => $chart_data['labels'],
						'datasets' => array(
							array(
								'type'        => 'bar',
								/* translators: %s: currency symbol */
								'label'       => sprintf( __( 'Amount donated (%s)', 'ambassadorhub' ), SettingsManager::get_currency_symbol() ),
								'data'        => $chart_data['amounts'],
								'borderWidth' => 1,
								'yAxisID'     => 'y',
							),
							array(
								'type'        => 'line',
								'label'       => __( 'Number of donors', 'ambassadorhub' ),
								'data'        => $chart_data['donors'],
								'borderWidth' => 3,
								'tension'     => 0,
								'fill'        => false,
								'yAxisID'     => 'y1',
							),
						),
					),
					'options' => array(
						'scales' => array(
							'y'  => array(
								'beginAtZero' => true,
								'position'    => 'left',
							),
							'y1' => array(
								'beginAtZero' => true,
								'position'    => 'right',
								'grid'        => array( 'drawOnChartArea' => false ),
							),
						),
					),
				)
			);
			?>
		<?php endif; ?>
		<?php
	}

	/**
	 * Get KPI totals for a campaign: donation count, total amount, average amount
	 * across all fundraisers belonging to this campaign.
	 *
	 * @param int $campaign_id Campaign post ID.
	 * @return array{count: int, total: float, average: float}
	 */
	private static function get_campaign_kpi_data( int $campaign_id ): array {
		global $wpdb;
		$table          = esc_sql( DonationsModule::get_table_name() );
		$posts_table    = esc_sql( $wpdb->posts );
		$postmeta_table = esc_sql( $wpdb->postmeta );
		$post_type      = FundraisersModule::POST_TYPE;

		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$row = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT COUNT(*) AS total_count, SUM(d.amount) AS total_amount, AVG(d.amount) AS avg_amount
				FROM {$table} d
				INNER JOIN {$posts_table} p ON p.ID = d.fundraiser_id AND p.post_type = %s
				INNER JOIN {$postmeta_table} pm ON pm.post_id = p.ID AND pm.meta_key = '_ambh_campaign_id' AND pm.meta_value = %d
				WHERE d.status = %s",
				$post_type,
				$campaign_id,
				'completed'
			)
		);
		// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		return array(
			'count'   => (int) ( $row->total_count ?? 0 ),
			'total'   => (float) ( $row->total_amount ?? 0 ),
			'average' => (float) ( $row->avg_amount ?? 0 ),
		);
	}

	/**
	 * Get monthly donation amounts and donor counts for the past 12 months,
	 * aggregated across all fundraisers belonging to this campaign.
	 *
	 * @param int $campaign_id Campaign post ID.
	 * @return array{labels: string[], amounts: float[], donors: int[]}
	 */
	private static function get_campaign_chart_data( int $campaign_id ): array {
		global $wpdb;
		$table          = esc_sql( DonationsModule::get_table_name() );
		$posts_table    = esc_sql( $wpdb->posts );
		$postmeta_table = esc_sql( $wpdb->postmeta );
		$post_type      = FundraisersModule::POST_TYPE;

		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$rows = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT
					DATE_FORMAT(d.created_at, '%%Y-%%m') AS month,
					SUM(d.amount)                        AS total_amount,
					COUNT(DISTINCT d.donor_id)           AS total_donors
				FROM {$table} d
				INNER JOIN {$posts_table} p ON p.ID = d.fundraiser_id AND p.post_type = %s
				INNER JOIN {$postmeta_table} pm ON pm.post_id = p.ID AND pm.meta_key = '_ambh_campaign_id' AND pm.meta_value = %d
				WHERE d.status = %s
				  AND d.created_at >= DATE_SUB(NOW(), INTERVAL 12 MONTH)
				GROUP BY month
				ORDER BY month ASC",
				$post_type,
				$campaign_id,
				'completed'
			)
		);
		// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		$labels  = array();
		$amounts = array();
		$donors  = array();

		foreach ( $rows as $row ) {
			$labels[]  = $row->month;
			$amounts[] = (float) $row->total_amount;
			$donors[]  = (int) $row->total_donors;
		}

		return compact( 'labels', 'amounts', 'donors' );
	}

	/**
	 * Get the fundraising goal for a campaign.
	 *
	 * Uses the campaign-level `_ambh_financial_goal` when set (> 0).
	 * Falls back to the sum of `_ambh_target_amount` across all fundraisers
	 * assigned to this campaign when no campaign goal is set.
	 *
	 * @param int $campaign_id Campaign post ID.
	 * @return float Goal amount (0 if neither is set).
	 */
	private static function get_campaign_goal( int $campaign_id ): float {
		// Prefer the explicit campaign-level financial goal.
		$campaign_goal = (float) get_post_meta( $campaign_id, '_ambh_financial_goal', true );
		if ( $campaign_goal > 0 ) {
			return $campaign_goal;
		}

		// Fall back to the sum of per-fundraiser target amounts.
		global $wpdb;
		$posts_table    = $wpdb->posts;
		$postmeta_table = $wpdb->postmeta;
		$post_type      = FundraisersModule::POST_TYPE;

		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$total = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT SUM(CAST(pm_target.meta_value AS DECIMAL(15,2)))
				FROM {$posts_table} p
				INNER JOIN {$postmeta_table} pm_campaign
					ON pm_campaign.post_id = p.ID
					AND pm_campaign.meta_key = '_ambh_campaign_id'
					AND pm_campaign.meta_value = %d
				INNER JOIN {$postmeta_table} pm_target
					ON pm_target.post_id = p.ID
					AND pm_target.meta_key = '_ambh_target_amount'
				WHERE p.post_type = %s
				  AND p.post_status != 'trash'",
				$campaign_id,
				$post_type
			)
		);
		// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		return (float) ( $total ?? 0 );
	}
}
