<?php
/**
 * Wires custom-email triggers (status change, time delay).
 *
 * @package Kramar
 * @since   1.0.0
 */

declare( strict_types=1 );

namespace Kramar\Modules\Email;

defined( 'ABSPATH' ) || exit;

/**
 * @since 1.0.0
 */
final class Custom_Email_Triggers {

	public function __construct( private Email_Manager $manager ) {}

	/**
	 * Register trigger hooks for all enabled custom emails.
	 *
	 * @since 1.0.0
	 */
	public function register(): void {
		add_action( 'woocommerce_order_status_changed', [ $this, 'handle_status' ], 10, 4 );

		// Delay anchors: placed, paid, completed.
		add_action( 'woocommerce_checkout_order_processed', [ $this, 'handle_anchor_placed' ], 20 );
		add_action( 'woocommerce_payment_complete', [ $this, 'handle_anchor_paid' ], 20 );
		add_action( 'woocommerce_order_status_completed', [ $this, 'handle_anchor_completed' ], 20 );

		// Dynamic status anchors: for any enabled delay email with anchor === 'status',
		// register a hook on woocommerce_order_status_{anchor_status}.
		$custom = get_option( 'kramar_custom_emails', [] );
		if ( is_array( $custom ) ) {
			foreach ( $custom as $config ) {
				if ( empty( $config['enabled'] ) || 'delay' !== ( $config['trigger_type'] ?? '' ) ) {
					continue;
				}
				if ( 'status' !== ( $config['anchor'] ?? '' ) ) {
					continue;
				}
				$raw    = (string) ( $config['anchor_status'] ?? '' );
				$status = str_starts_with( $raw, 'wc-' ) ? substr( $raw, 3 ) : $raw;
				if ( '' === $status ) {
					continue;
				}
				add_action( 'woocommerce_order_status_' . $status, [ $this, 'handle_anchor_status' ], 20 );
			}
		}
	}

	/**
	 * Fire status-change custom emails on a matching transition.
	 *
	 * @since 1.0.0
	 *
	 * @param int    $order_id   Order id.
	 * @param string $from       Previous status (no wc- prefix).
	 * @param string $to         New status (no wc- prefix).
	 * @param object $order      The order object.
	 */
	public function handle_status( int $order_id, string $from, string $to, $order ): void {
		$custom = get_option( 'kramar_custom_emails', [] );
		if ( ! is_array( $custom ) ) {
			return;
		}

		foreach ( $custom as $id => $config ) {
			if ( empty( $config['enabled'] ) || 'status_change' !== ( $config['trigger_type'] ?? '' ) ) {
				continue;
			}
			$raw_to    = (string) ( $config['trigger_to'] ?? '' );
			$want_to   = str_starts_with( $raw_to, 'wc-' ) ? substr( $raw_to, 3 ) : $raw_to;
			$raw_from  = (string) ( $config['trigger_from'] ?? '' );
			$want_from = str_starts_with( $raw_from, 'wc-' ) ? substr( $raw_from, 3 ) : $raw_from;
			if ( '' === $want_to || $to !== $want_to ) {
				continue;
			}
			if ( '' !== $want_from && $from !== $want_from ) {
				continue;
			}
			$this->manager->send_custom_email( (string) $id, $order_id );
		}

		// Cancel pending delayed sends when the order reaches a disqualifying status.
		$cancel = (array) apply_filters( 'kramar_email_cancel_statuses', [ 'cancelled', 'refunded', 'failed' ] );
		if ( in_array( $to, $cancel, true ) ) {
			$this->cancel_for_order( $order_id );
		}
	}

	/**
	 * @since 1.0.0
	 */
	public function handle_anchor_placed( int $order_id ): void {
		$this->schedule_anchor( 'placed', $order_id );
	}

	/**
	 * @since 1.0.0
	 */
	public function handle_anchor_paid( int $order_id ): void {
		$this->schedule_anchor( 'paid', $order_id );
	}

	/**
	 * @since 1.0.0
	 */
	public function handle_anchor_completed( int $order_id ): void {
		$this->schedule_anchor( 'completed', $order_id );
	}

	/**
	 * Handle a dynamic status anchor hook (woocommerce_order_status_{status}).
	 *
	 * @since 1.0.0
	 */
	public function handle_anchor_status( int $order_id ): void {
		// current_filter() gives us woocommerce_order_status_{status}.
		$hook   = current_filter();
		$prefix = 'woocommerce_order_status_';
		$status = str_starts_with( $hook, $prefix ) ? substr( $hook, strlen( $prefix ) ) : '';
		if ( '' === $status ) {
			return;
		}
		$this->schedule_anchor( 'status:' . $status, $order_id );
	}

	/**
	 * Schedule delayed custom emails for a given anchor event.
	 *
	 * @since 1.0.0
	 */
	private function schedule_anchor( string $anchor, int $order_id ): void {
		$custom = get_option( 'kramar_custom_emails', [] );
		if ( ! is_array( $custom ) ) {
			return;
		}
		foreach ( $custom as $id => $config ) {
			if ( empty( $config['enabled'] ) || 'delay' !== ( $config['trigger_type'] ?? '' ) ) {
				continue;
			}
			$cfg_anchor = (string) ( $config['anchor'] ?? 'completed' );

			// For status anchors, build the compound key for comparison.
			if ( 'status' === $cfg_anchor ) {
				$raw    = (string) ( $config['anchor_status'] ?? '' );
				$status = str_starts_with( $raw, 'wc-' ) ? substr( $raw, 3 ) : $raw;
				$cfg_anchor = 'status:' . $status;
			}

			if ( $anchor !== $cfg_anchor ) {
				continue;
			}
			$value = max( 0, (int) ( $config['delay_value'] ?? 0 ) );
			$unit  = 'hours' === ( $config['delay_unit'] ?? 'days' ) ? HOUR_IN_SECONDS : DAY_IN_SECONDS;
			$this->manager->schedule_custom_email( (string) $id, $order_id, time() + ( $value * $unit ) );
		}
	}

	/**
	 * Unschedule all pending delayed custom-email sends for an order.
	 *
	 * @since 1.0.0
	 */
	public function cancel_for_order( int $order_id ): void {
		if ( ! function_exists( 'as_unschedule_all_actions' ) ) {
			return;
		}
		$custom = get_option( 'kramar_custom_emails', [] );
		foreach ( is_array( $custom ) ? array_keys( $custom ) : [] as $id ) {
			as_unschedule_all_actions( 'kramar_send_custom_email', [ 'email_id' => (string) $id, 'order_id' => $order_id ], 'kramar' );
		}
	}
}
