<?php
/**
 * Stripe Checkout session factory.
 *
 * @package Donatico\Stripe
 */

declare(strict_types=1);

namespace Donatico\Stripe;

use Donatico\Models\Donation;

/**
 * Creates Stripe Checkout sessions for a given Donation.
 * The returned session URL is what the browser is redirected to.
 */
class CheckoutSession {

	/** @var StripeClient */
	private StripeClient $stripeClient;

	/**
	 * @param StripeClient $stripeClient
	 */
	public function __construct( StripeClient $stripeClient ) {
		$this->stripeClient = $stripeClient;
	}

	/**
	 * Create and return a Stripe Checkout session for the given donation.
	 *
	 * @param Donation $donation A persisted donation (must have an ID).
	 * @return \Stripe\Checkout\Session
	 * @throws \Stripe\Exception\ApiErrorException On any Stripe API failure.
	 */
	public function create( Donation $donation ): \Stripe\Checkout\Session {
		$client       = $this->stripeClient->getClient();
		$base_url     = trailingslashit( home_url() );
		$product_name = $this->buildProductName();

		$default_metadata = array(
			'donation_id'  => (string) $donation->getId(),
			'donor_name'   => $donation->getDonorName(),
			'is_anonymous' => $donation->isAnonymous() ? '1' : '0',
			'plugin'       => 'donatico',
			'mode'         => $this->stripeClient->getMode(),
		);

		/**
		 * Filter the Stripe Checkout session metadata.
		 *
		 * Allows plugins to add extra key/value pairs that travel with the
		 * checkout session and are returned in webhook events. Stripe
		 * limits metadata to 50 keys, max 40 chars per key, 500 chars per
		 * value.
		 *
		 * @param array    $metadata Default 5-key metadata array.
		 * @param Donation $donation The donation being checked out.
		 */
		$metadata = apply_filters( 'donatico_checkout_session_metadata', $default_metadata, $donation );

		$session = $client->checkout->sessions->create(
			array(
				'mode'                 => 'payment',
				'payment_method_types' => array( 'card' ),

				'line_items' => array(
					array(
						'price_data' => array(
							'currency'     => strtolower( $donation->getCurrency() ),
							'product_data' => array(
								'name'        => $product_name,
								'description' => $donation->getMessage()
									?: __( 'Thank you for your support!', 'donatico' ),
							),
							'unit_amount'  => $donation->getAmount(), // already in cents
						),
						'quantity'   => 1,
					),
				),

				'customer_email' => $donation->getDonorEmail(),

				// Metadata is returned in webhook events — lets us look up the
				// donation row without an extra API call.
				'metadata' => $metadata,

				// {CHECKOUT_SESSION_ID} is a Stripe template literal replaced
				// server-side before the redirect. Appended raw so Stripe receives
				// the literal string and substitutes it correctly.
				'success_url' => $base_url . '?donatico_action=success&session_id={CHECKOUT_SESSION_ID}',
				'cancel_url'  => $base_url . '?donatico_action=cancel&session_id={CHECKOUT_SESSION_ID}',
			)
		);

		return $session;
	}

	/**
	 * Build a human-readable product name for the Stripe Checkout page.
	 *
	 * @return string
	 */
	private function buildProductName(): string {
		$site_name = get_bloginfo( 'name' );
		/* translators: %s: site name */
		return $site_name ? sprintf( __( 'Donation to %s', 'donatico' ), $site_name ) : __( 'Donation', 'donatico' );
	}
}
