<?php
/**
 * GGM Commerce Subscription Email Template Base Class
 * Base class for subscription-specific emails.
 *
 * @package GGM_Commerce
 */

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

/**
 * Abstract subscription email base class.
 *
 * Overrides the order-centric trigger/placeholder logic
 * from GGM_Commerce_Email_Template to work with subscription data.
 */
abstract class GGM_Commerce_Email_Subscription_Template extends GGM_Commerce_Email_Template {

	/**
	 * Current subscription object.
	 *
	 * @var object|null
	 */
	protected $subscription = null;

	/**
	 * Trigger the subscription email.
	 *
	 * @param int   $subscription_id Subscription ID.
	 * @param array $extra_args      Extra arguments.
	 * @return bool
	 */
	public function trigger( $subscription_id, $extra_args = array() ) {
		$sub_manager    = GGM_Commerce_Subscriptions::instance();
		$subscription   = $sub_manager->get_subscription( $subscription_id );

		if ( ! $subscription ) {
			return false;
		}

		$this->subscription = $subscription;

		// Build a minimal order-like object for the base template's wrap method.
		$order = $this->build_order_object( $subscription );

		// Get recipient.
		$recipient = $this->get_subscription_recipient( $subscription );
		if ( empty( $recipient ) ) {
			return false;
		}

		// Get subject and content.
		$subject = $this->get_subject( $order );
		$content = $this->get_content( $order, $extra_args );

		// Send email.
		$email_manager = ggm_commerce_emails();
		$sent          = $email_manager->send_email( $recipient, $subject, $content );

		// Log email.
		$email_manager->log_email(
			$this->id,
			$subscription->parent_order_id ?? 0,
			$recipient,
			$subject,
			$sent
		);

		return $sent;
	}

	/**
	 * Get recipient for subscription email.
	 *
	 * @param object $subscription Subscription object.
	 * @return string
	 */
	protected function get_subscription_recipient( $subscription ) {
		if ( 'admin' === $this->recipient_type ) {
			return ggm_commerce_emails()->get_admin_email();
		}

		return $subscription->customer_email ?? '';
	}

	/**
	 * Build an order-like object from subscription for the template system.
	 *
	 * @param object $subscription Subscription object.
	 * @return object
	 */
	protected function build_order_object( $subscription ) {
		// Fetch the parent order for address data.
		$order = null;
		if ( ! empty( $subscription->parent_order_id ) ) {
			$orders = GGM_Commerce_Orders::get_instance();
			$order  = $orders->get_order( $subscription->parent_order_id );
		}

		// Build a composite object with subscription + order data.
		$obj = new \stdClass();

		// Order fields (from parent order).
		$obj->id                  = $subscription->parent_order_id ?? 0;
		$obj->order_number        = $order->order_number ?? '';
		$obj->created_at          = $order->created_at ?? $subscription->start_date;
		$obj->total_amount        = $subscription->recurring_total;
		$obj->subtotal            = $subscription->recurring_amount;
		$obj->tax_amount          = $subscription->tax_amount ?? 0;
		$obj->shipping_amount     = $subscription->shipping_amount ?? 0;
		$obj->status              = $order->status ?? '';
		$obj->payment_status      = $order->payment_status ?? '';
		$obj->payment_method      = $subscription->payment_gateway ?? '';

		// Customer fields.
		$obj->customer_email      = $subscription->customer_email;
		$obj->customer_first_name = $order->customer_first_name ?? '';
		$obj->customer_last_name  = $order->customer_last_name ?? '';

		// Address fields from parent order.
		if ( $order ) {
			foreach ( array( 'billing', 'shipping' ) as $type ) {
				foreach ( array( 'first_name', 'last_name', 'company', 'address_1', 'address_2', 'city', 'state', 'postcode', 'country' ) as $field ) {
					$key       = $type . '_' . $field;
					$obj->$key = $order->$key ?? '';
				}
			}
		}

		// Items (empty for subscription emails — we render subscription details instead).
		$obj->items = array();

		return $obj;
	}

	/**
	 * Get placeholder values for subscription emails.
	 *
	 * @param object $order      Order-like object.
	 * @param array  $extra_args Extra arguments.
	 * @return array
	 */
	protected function get_placeholder_values( $order, $extra_args = array() ) {
		// Get base placeholders from parent.
		$placeholders = parent::get_placeholder_values( $order, $extra_args );

		// Add subscription-specific placeholders.
		$sub = $this->subscription;
		if ( ! $sub ) {
			return $placeholders;
		}

		$currency_options = get_option( 'ggm_commerce_currency_options', array() );
		$currency_symbol  = isset( $currency_options['symbol'] ) ? $currency_options['symbol'] : '$';

		$billing_periods = GGM_Commerce_Subscriptions::get_billing_periods();
		$statuses        = GGM_Commerce_Subscriptions::get_statuses();
		$period_label    = $billing_periods[ $sub->billing_period ] ?? $sub->billing_period;

		$cycle_text = (int) $sub->billing_interval === 1
			? $currency_symbol . number_format( (float) $sub->recurring_total, 2 ) . '/' . rtrim( $period_label, '(s)' )
			: $currency_symbol . number_format( (float) $sub->recurring_total, 2 ) . ' every ' . (int) $sub->billing_interval . ' ' . $period_label;

		// Fetch product name.
		$product_name = '';
		if ( ! empty( $sub->product_id ) ) {
			global $wpdb;
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$product = $wpdb->get_var( $wpdb->prepare(
				"SELECT name FROM {$wpdb->prefix}ggmc_products WHERE id = %d",
				$sub->product_id
			) );
			$product_name = $product ?? '';
		}

		$placeholders['subscription_number']       = $sub->subscription_number ?? '';
		$placeholders['subscription_status']        = $statuses[ $sub->status ] ?? ucfirst( str_replace( '_', ' ', $sub->status ) );
		$placeholders['subscription_amount']        = $currency_symbol . number_format( (float) $sub->recurring_total, 2 );
		$placeholders['subscription_cycle']         = $cycle_text;
		$placeholders['subscription_product']       = $product_name;
		$placeholders['subscription_start_date']    = ! empty( $sub->start_date ) ? gmdate( 'F j, Y', strtotime( $sub->start_date ) ) : '';
		$placeholders['subscription_next_payment']  = ! empty( $sub->next_payment_date ) && '0000-00-00 00:00:00' !== $sub->next_payment_date
			? gmdate( 'F j, Y', strtotime( $sub->next_payment_date ) ) : __( 'N/A', 'ggm-commerce' );
		$placeholders['subscription_end_date']      = ! empty( $sub->end_date ) && '0000-00-00 00:00:00' !== $sub->end_date
			? gmdate( 'F j, Y', strtotime( $sub->end_date ) ) : __( 'Until cancelled', 'ggm-commerce' );
		$placeholders['subscription_trial_end']     = ! empty( $sub->trial_end_date ) && '0000-00-00 00:00:00' !== $sub->trial_end_date
			? gmdate( 'F j, Y', strtotime( $sub->trial_end_date ) ) : '';
		$placeholders['subscription_payment_method'] = ucfirst( $sub->payment_gateway ?? '' );

		// Extra args can override values.
		if ( ! empty( $extra_args['retry_number'] ) ) {
			$placeholders['retry_number'] = (int) $extra_args['retry_number'];
		}
		if ( ! empty( $extra_args['retry_date'] ) ) {
			$placeholders['retry_date'] = gmdate( 'F j, Y', strtotime( $extra_args['retry_date'] ) );
		}
		if ( ! empty( $extra_args['cancellation_reason'] ) ) {
			$placeholders['cancellation_reason'] = $extra_args['cancellation_reason'];
		}
		if ( ! empty( $extra_args['days_remaining'] ) ) {
			$placeholders['days_remaining'] = (int) $extra_args['days_remaining'];
		}

		return $placeholders;
	}

	/**
	 * Get available placeholders for subscription emails.
	 *
	 * @return array
	 */
	public function get_placeholders() {
		$base = parent::get_placeholders();

		return array_merge( $base, array(
			'subscription_number'         => __( 'Subscription number', 'ggm-commerce' ),
			'subscription_status'         => __( 'Subscription status', 'ggm-commerce' ),
			'subscription_amount'         => __( 'Recurring amount', 'ggm-commerce' ),
			'subscription_cycle'          => __( 'Billing cycle text (e.g. $9.99/month)', 'ggm-commerce' ),
			'subscription_product'        => __( 'Product name', 'ggm-commerce' ),
			'subscription_start_date'     => __( 'Start date', 'ggm-commerce' ),
			'subscription_next_payment'   => __( 'Next payment date', 'ggm-commerce' ),
			'subscription_end_date'       => __( 'End date', 'ggm-commerce' ),
			'subscription_trial_end'      => __( 'Trial end date', 'ggm-commerce' ),
			'subscription_payment_method' => __( 'Payment method', 'ggm-commerce' ),
		) );
	}

	/**
	 * Render subscription details block (HTML).
	 *
	 * @return string
	 */
	protected function render_subscription_details_block() {
		return '
<div class="address-box" style="margin: 24px 0;">
	<h4 style="margin: 0 0 8px 0;">Subscription Details</h4>
	<p><strong>Subscription:</strong> #{subscription_number}<br>
	<strong>Product:</strong> {subscription_product}<br>
	<strong>Billing Cycle:</strong> {subscription_cycle}<br>
	<strong>Status:</strong> {subscription_status}<br>
	<strong>Next Payment:</strong> {subscription_next_payment}</p>
</div>';
	}

	/**
	 * Get sample order for preview (subscription variant).
	 *
	 * @return object
	 */
	protected function get_sample_order() {
		$order = parent::get_sample_order();

		// The preview system needs subscription placeholders.
		// We fake them via extra property.
		return $order;
	}

	/**
	 * Override replace_placeholders to inject sample subscription data for previews.
	 *
	 * @param string $content    Content with placeholders.
	 * @param object $order      Order object.
	 * @param array  $extra_args Extra arguments.
	 * @return string
	 */
	protected function replace_placeholders( $content, $order, $extra_args = array() ) {
		// If we have no real subscription, add sample subscription placeholders.
		if ( null === $this->subscription ) {
			$sample_placeholders = array(
				'{subscription_number}'         => 'SUB-00042',
				'{subscription_status}'         => 'Active',
				'{subscription_amount}'         => '$9.99',
				'{subscription_cycle}'          => '$9.99/month',
				'{subscription_product}'        => 'Premium Plan',
				'{subscription_start_date}'     => gmdate( 'F j, Y' ),
				'{subscription_next_payment}'   => gmdate( 'F j, Y', strtotime( '+1 month' ) ),
				'{subscription_end_date}'       => 'Until cancelled',
				'{subscription_trial_end}'      => gmdate( 'F j, Y', strtotime( '+14 days' ) ),
				'{subscription_payment_method}' => 'Stripe',
				'{retry_number}'                => '1',
				'{retry_date}'                  => gmdate( 'F j, Y', strtotime( '+3 days' ) ),
				'{cancellation_reason}'         => 'Customer requested cancellation',
				'{days_remaining}'              => '3',
			);
			$content = str_replace( array_keys( $sample_placeholders ), array_values( $sample_placeholders ), $content );
		}

		return parent::replace_placeholders( $content, $order, $extra_args );
	}
}
