<?php
/**
 * Cart Recovery — Analytics Dashboard widget
 *
 * Renders a Cart Recovery card inside the main Niwa AI analytics page
 * using the same `niwa-card` + `niwa-stats` + `render_stat_card`
 * pattern Analytics_Dashboard already uses for its own sections.
 *
 * Wires via the `niwa_ai_analytics_dashboard_extra_sections` action
 * (new in Phase 7) so future modules can slot in without touching the
 * dashboard class. Analytics_Dashboard fires the action near the end
 * of `render_page()` with the current `$filters` context; listeners
 * receive the filters and the dashboard instance for helper access.
 *
 * Graceful: if the repository query explodes for any reason, the card
 * renders zeros rather than blanking the whole analytics page.
 *
 * @package Niwa_AI
 * @since   0.12.0
 */

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

class Niwa_AI_Cart_Recovery_Analytics_Widget {

	public function __construct(
		private readonly Niwa_AI_Cart_Recovery_Repository $repository
	) {}

	public function register_hooks(): void {
		add_action( 'niwa_ai_analytics_dashboard_extra_sections', array( $this, 'render' ), 10, 2 );
	}

	/**
	 * Render callback. Signature mirrors how Analytics_Dashboard
	 * will fire the action: `($filters, $dashboard_instance)`.
	 *
	 * @param array<string, mixed> $filters
	 * @param object|null          $dashboard Analytics_Dashboard instance (for `render_stat_card` / `format_money`).
	 */
	public function render( $filters = array(), $dashboard = null ): void {
		$days = $this->resolve_window_days( $filters );

		try {
			$metrics = $this->repository->get_metrics( $days );
		} catch ( \Throwable $e ) {
			$metrics = array(
				'sent' => 0, 'sent_mail1' => 0, 'sent_mail2' => 0,
				'opens' => 0, 'clicks' => 0, 'recovered' => 0,
				'pending' => 0, 'suppression' => 0,
				'open_rate' => 0.0, 'click_rate' => 0.0, 'recovered_rate' => 0.0,
				'recovered_revenue' => 0.0,
			);
		}

		$helper = ( is_object( $dashboard ) && method_exists( $dashboard, 'render_stat_card' ) ) ? $dashboard : null;

		echo '<div class="niwa-card"><div class="niwa-card__header">';
		echo '<h2 class="niwa-card__title">' . esc_html__( 'Cart Recovery', 'niwa-ai' ) . '</h2>';
		echo '</div><div class="niwa-card__body"><div class="niwa-stats">';

		$this->render_stat( $helper, __( 'Reminders Sent', 'niwa-ai' ), (string) (int) $metrics['sent'] );
		$this->render_stat( $helper, __( 'Opens', 'niwa-ai' ),          (string) (int) $metrics['opens'] );
		$this->render_stat( $helper, __( 'Open Rate', 'niwa-ai' ),      $this->format_rate( $metrics['open_rate'] ) );
		$this->render_stat( $helper, __( 'Clicks', 'niwa-ai' ),         (string) (int) $metrics['clicks'] );
		$this->render_stat( $helper, __( 'Click Rate', 'niwa-ai' ),     $this->format_rate( $metrics['click_rate'] ) );
		$this->render_stat( $helper, __( 'Recovered', 'niwa-ai' ),      (string) (int) $metrics['recovered'] );
		$this->render_stat( $helper, __( 'Recovery Rate', 'niwa-ai' ),  $this->format_rate( $metrics['recovered_rate'] ) );
		$this->render_stat( $helper, __( 'Recovered Revenue', 'niwa-ai' ), $this->format_money( $dashboard, (float) $metrics['recovered_revenue'] ) );

		echo '</div></div></div>';
	}

	/**
	 * Delegates to Analytics_Dashboard::render_stat_card when available
	 * so the visual matches the rest of the dashboard exactly. Falls
	 * back to a minimal inline markup otherwise (partial install).
	 */
	private function render_stat( $dashboard, string $label, string $value ): void {
		if ( is_object( $dashboard ) && method_exists( $dashboard, 'render_stat_card' ) ) {
			$dashboard->render_stat_card( $label, $value );
			return;
		}
		echo '<div class="niwa-stat"><div class="niwa-stat__label">' . esc_html( $label ) . '</div><div class="niwa-stat__value">' . esc_html( $value ) . '</div></div>';
	}

	private function format_rate( $rate ): string {
		return number_format_i18n( (float) $rate, 1 ) . '%';
	}

	private function format_money( $dashboard, float $amount ): string {
		if ( is_object( $dashboard ) && method_exists( $dashboard, 'format_money' ) ) {
			return (string) $dashboard->format_money( $amount );
		}
		if ( function_exists( 'wc_price' ) ) {
			return wp_strip_all_tags( (string) wc_price( $amount ) );
		}
		return number_format_i18n( $amount, 2 );
	}

	private function resolve_window_days( array $filters ): int {
		if ( isset( $filters['days'] ) && is_numeric( $filters['days'] ) ) {
			return max( 1, min( 365, (int) $filters['days'] ) );
		}
		if ( isset( $filters['range_days'] ) && is_numeric( $filters['range_days'] ) ) {
			return max( 1, min( 365, (int) $filters['range_days'] ) );
		}
		return 30;
	}
}
