<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Issues documents when configured WooCommerce order statuses are reached.
 * WooCommerce remains solely responsible for sending transactional emails.
 */
class PBUAIV_Order_Hooks {

    private static ?PBUAIV_Order_Hooks $instance = null;

    /** @var array<int,bool> */
    private array $processing_orders = [];

    public static function instance() : self {
        if ( null === self::$instance ) self::$instance = new self();
        return self::$instance;
    }

    private function __construct() {
        add_action( 'woocommerce_order_status_changed', [ $this, 'on_status_change' ], 1, 4 );
        add_action( 'woocommerce_order_fully_refunded', [ $this, 'on_refund' ], 1, 2 );
        add_action( 'woocommerce_order_partially_refunded', [ $this, 'on_refund' ], 1, 2 );
    }

    public function on_status_change( int $order_id, string $old_status, string $new_status, WC_Order $order ) : void {
        unset( $old_status );

        if ( isset( $this->processing_orders[ $order_id ] ) ) {
            return;
        }

        $this->processing_orders[ $order_id ] = true;

        try {
            foreach ( PBUAIV_Settings_Schema::automation_rules() as $doc_type => $rule ) {
                $statuses = PBUAIV_Settings_Schema::get_array_option( $rule['option'] );
                if ( ! in_array( $new_status, $statuses, true ) ) {
                    continue;
                }

                $doc = PBUAIV_Email_Manager::factory( $doc_type, $order );
                if ( $doc && ! $doc->is_issued() ) {
                    $doc->issue();
                }
                unset( $doc );
            }
        } finally {
            unset( $this->processing_orders[ $order_id ] );
        }
    }

    public function on_refund( int $order_id, int $refund_id ) : void {
        unset( $refund_id );

        $rules = PBUAIV_Settings_Schema::automation_rules();
        if ( ! isset( $rules['credit_note'] ) ) {
            return;
        }

        $statuses = PBUAIV_Settings_Schema::get_array_option( $rules['credit_note']['option'] );
        if ( ! in_array( 'refunded', $statuses, true ) ) {
            return;
        }

        $order = wc_get_order( $order_id );
        if ( ! $order ) {
            return;
        }

        $doc = new PBUAIV_Credit_Note( $order );
        if ( ! $doc->is_issued() ) {
            $doc->issue();
        }
    }
}
