<?php
/**
 * Donation form renderer.
 *
 * @package Donatico\Frontend
 */

declare(strict_types=1);

namespace Donatico\Frontend;

use Donatico\Database\DonationRepository;
use Donatico\Helpers\Currency;

/**
 * Builds the template variable set and renders the correct form layout template.
 * Each call to render() receives a unique form ID so multiple forms on the
 * same page don't collide in the DOM or JavaScript handlers.
 */
class FormRenderer {

	/** Incremented per render() call to generate unique DOM IDs. */
	private static int $counter = 0;

	/** @var DonationRepository */
	private DonationRepository $repository;

	/** @var Assets */
	private Assets $assets;

	/**
	 * @param DonationRepository $repository
	 * @param Assets             $assets
	 */
	public function __construct( DonationRepository $repository, Assets $assets ) {
		$this->repository = $repository;
		$this->assets     = $assets;
	}

	/**
	 * Render the donation form and return its HTML.
	 *
	 * @param array<string, mixed> $atts Shortcode attributes, already merged with defaults.
	 * @return string
	 */
	public function render( array $atts ): string {
		// Ensure assets are loaded even when wp_enqueue_scripts has already fired
		// (e.g. widget areas, page builders, late template loading).
		$this->assets->enqueueNow();

		self::$counter++;
		$form_id = 'donatico-form-' . self::$counter;

		// ---- Normalise attributes ----
		$layout         = $this->sanitizeLayout( (string) ( $atts['layout'] ?? 'stacked' ) );
		$amounts        = $this->parseAmounts( (string) ( $atts['amounts'] ?? '' ) );
		$title          = sanitize_text_field( (string) ( $atts['title'] ?? '' ) );
		$description    = sanitize_text_field( (string) ( $atts['description'] ?? '' ) );
		$button_text    = sanitize_text_field( (string) ( $atts['button_text'] ?? __( 'Donate Now', 'donatico' ) ) );
		$show_message   = ( ( $atts['show_message'] ?? 'yes' ) !== 'no' );
		$allow_anonymous = ( ( $atts['allow_anonymous'] ?? 'yes' ) !== 'no' );

		// ---- Currency ----
		$currency        = (string) get_option( 'donatico_currency', 'USD' );
		$currency_symbol = Currency::getSymbol( $currency );

		// ---- Goal & progress ----
		$goal = isset( $atts['goal'] ) && $atts['goal'] !== ''
			? absint( $atts['goal'] )
			: (int) get_option( 'donatico_goal_amount', 0 );

		$total_raised = 0;
		$progress     = 0;

		if ( $goal > 0 ) {
			$stats        = $this->repository->getStats();
			$total_raised = $stats['total_amount']; // cents
			$raised_major = $total_raised / 100;
			$progress     = min( 100, (int) round( ( $raised_major / $goal ) * 100 ) );
		}

		// ---- Security nonce ----
		$nonce = wp_create_nonce( 'donatico_checkout' );

		// ---- Capture template output ----
		$template = DONATICO_PLUGIN_DIR . 'templates/frontend/form-' . $layout . '.php';

		if ( ! file_exists( $template ) ) {
			return '<!-- Donatico: template not found for layout "' . esc_html( $layout ) . '" -->';
		}

		ob_start();
		include $template;
		return (string) ob_get_clean();
	}

	// -------------------------------------------------------------------------
	// Helpers (also used by FormDesigner)
	// -------------------------------------------------------------------------

	/**
	 * Validate and return a layout slug. Falls back to 'stacked'.
	 *
	 * @param string $layout
	 * @return string
	 */
	public static function sanitizeLayout( string $layout ): string {
		$allowed = array( 'inline', 'stacked', 'card' );
		return in_array( $layout, $allowed, true ) ? $layout : 'stacked';
	}

	/**
	 * Parse a comma-separated amount string into an integer array.
	 * Falls back to the stored preset_amounts option.
	 *
	 * @param string $raw
	 * @return int[]
	 */
	public static function parseAmounts( string $raw ): array {
		if ( $raw !== '' ) {
			$parts = explode( ',', $raw );
		} else {
			$stored = get_option( 'donatico_preset_amounts', array( 5, 10, 25, 50, 100 ) );
			$parts  = is_array( $stored ) ? $stored : explode( ',', (string) $stored );
		}

		$amounts = array_values(
			array_filter(
				array_map( 'absint', $parts )
			)
		);

		return $amounts ?: array( 5, 10, 25, 50, 100 );
	}
}
