<?php

namespace YayMail\Shortcodes;

use YayMail\Utils\SingletonTrait;
use YayMail\Abstracts\BaseShortcode;

/**
 * @method: static HookShortcodes get_instance()
 */
class HookShortcodes extends BaseShortcode {
    use SingletonTrait;

    public function get_shortcodes() {
        $shortcodes   = [];
        $shortcodes[] = [
            'name'        => 'yaymail_custom_hook',
            'description' => __( 'YayMail custom hook', 'yaymail' ),
            'group'       => 'none',
            'callback'    => [ $this, 'main_callback' ],
        ];

        return $shortcodes;
    }

    /**
     * Main callback function to process a custom hook shortcode.
     *
     * @param array    $data The data associated with the shortcode execution, typically template data.
     *                Example: ['template' => YayMail\YayMailTemplate, 'render_data' => [], 'settings' => []].
     * @param string[] $attr_strings An array of attribute strings that need to be parsed into attribute tuples.
     *                Example: ["hook="yaydp_on_sale_products"", "limit="6"", "sale_price_color="#ec4770""].
     *
     * @return string The HTML content generated by processing the custom hook shortcode.
     */
    public function main_callback( $data, $attr_strings ) {
        // $attr_tuples = $this->get_attributes_from_strings( $attr_strings );
        return $this->yaymail_handle_custom_hook_shortcode( $data, $attr_strings );
    }

    /**
     * Process a custom hook shortcode and generate HTML content.
     *
     * @param array $data The data associated with the shortcode execution, typically template data.
     *                   Example: ['template' => YayMail\YayMailTemplate, 'render_data' => [], 'settings' => []].
     * @param array $attr_tuples An array of attribute tuples containing hook name and display settings.
     *                   Example: ['hook' => 'yaydp_on_sale_products', 'limit' => '6'].
     * @return string The HTML content generated by processing the custom hook shortcode.
     */
    public function yaymail_handle_custom_hook_shortcode( $data, $attr_tuples ) {
        $hook_name = isset( $attr_tuples['hook'] ) ? $attr_tuples['hook'] : '';

        switch ( $hook_name ) {
            case 'yaydp_on_sale_products':
                return $this->yaymail_render_yaydp_on_sale_products( $attr_tuples );
            case 'woocommerce_email_before_order_table':
            case 'woocommerce_email_after_order_table':
                return $this->yaymail_woocommerce_email_order_table( $data, $hook_name );
            default:
                return $this->yaymail_render_custom_hook_shortcode( $data, $hook_name );
        }

        return '';
    }

    /**
     * Generate HTML content for a custom hook related to WooCommerce email order tables.
     *
     * @param array  $data The data associated with the shortcode execution, typically template data.
     *                    Example: ['template' => YayMail\YayMailTemplate, 'render_data' => [], 'settings' => []].
     * @param string $hook_name The name of the hook associated with the WooCommerce email order table.
     *                    Example: "woocommerce_email_before_order_table".
     *
     * @return string The HTML content for the custom hook shortcode.
     */
    private function yaymail_woocommerce_email_order_table( $data, $hook_name ) {
        if ( empty( $data['render_data']['order'] ) ) {
            return '[' . $hook_name . ']';
        }

        $order = isset( $data['render_data']['order'] ) ? $data['render_data']['order'] : [];

        $sent_to_admin = isset( $data['send_to_admin'] ) ? $data['send_to_admin'] : false;
        $plain_text    = isset( $data['plain_text'] ) ? $data['plain_text'] : false;
        $email         = isset( $data['render_data']['email'] ) ? $data['render_data']['email'] : [];

        $hook_name = ! empty( $hook_name ) ? $hook_name : 'woocommerce_email_before_order_table';

        ob_start();
        do_action( $hook_name, $order, $sent_to_admin, $plain_text, $email );

        $content = ob_get_clean();

        return $content;
    }

    /**
     * Render HTML content for a custom hook shortcode.
     *
     * @param array  $data The data associated with the shortcode execution, containing template, render data and settings.
     * @param string $hook_name The name of the custom hook shortcode to execute.
     * @return string The HTML content generated by processing the custom hook shortcode.
     */
    private function yaymail_render_custom_hook_shortcode( $data, $hook_name ) {
        if ( empty( $hook_name ) || ! is_string( $hook_name ) ) {
            return '';
        }

        ob_start();

        do_action( $hook_name, $data );

        $content = ob_get_clean();

        return $content;
    }

    /**
     * Render HTML content for the 'yaydp_on_sale_products' hook.
     *
     * @param array $attr_tuples Attribute tuples for customizing on-sale products display.
     *                          Example: [
     *                              'limit' => '6',
     *                              'color' => 'inherit',
     *                              'background_color' => 'inherit',
     *                              'sale_price_color' => '#ec4770',
     *                              'regular_price_color' => '#808080',
     *                              'product_name_color' => '#636363',
     *                              'button_background_color' => '#ec4770',
     *                              'button_text_color' => '#ffffff'
     *                          ]
     * @return string Generated HTML content.
     */
    private function yaymail_render_yaydp_on_sale_products( $attr_tuples ) {
        if ( is_callable( 'yaydp_get_on_sale_products' ) ) {
            $products = yaydp_get_on_sale_products( $attr_tuples['limit'] );
            $args     = [
                'products'                => $products,
                'color'                   => esc_attr( $this->get_attribute( $attr_tuples, 'color' ) ),
                'background_color'        => esc_attr( $this->get_attribute( $attr_tuples, 'background_color' ) ),
                'sale_price_color'        => esc_attr( $this->get_attribute( $attr_tuples, 'sale_price_color', 'color' ) ),
                'regular_price_color'     => esc_attr( $this->get_attribute( $attr_tuples, 'regular_price_color', 'color' ) ),
                'product_name_color'      => esc_attr( $this->get_attribute( $attr_tuples, 'product_name_color', 'color' ) ),
                'button_background_color' => esc_attr( $this->get_attribute( $attr_tuples, 'button_background_color' ) ),
                'button_text_color'       => esc_attr( $this->get_attribute( $attr_tuples, 'button_text_color', 'color' ) ),
            ];
            $content  = yaymail_get_content( 'templates/shortcodes/yaydp-on-sale-products/main.php', $args );
            // We escape the content via yaymail_kses_post_e() in the template file
            return $content; // nosemgrep
        }
        return 'yaydp_on_sale_products';
    }

    /**
     * Extracts attributes from an array of strings in the format 'key="value"'.
     *
     * @param array $strings An array of strings containing attributes.
     *
     * @return array An array of attribute arrays, where each attribute array is associative ('key' => 'value').
     */
    private function get_attributes_from_strings( $strings ) {
        $result = [];

        if ( ! is_array( $strings ) ) {
            return $result;
        }
        foreach ( $strings as $str ) {
            preg_match_all( '/(\w+)="([^"]*?)"/', $str, $matches, PREG_SET_ORDER );

            foreach ( $matches as $match ) {
                $result[ $match[1] ] = $match[2];
            }
        }

        return $result;
    }

    /**
     * Get an attribute value with fallback.
     *
     * @param array       $attribute_tuples Attribute key-value pairs
     * @param string      $attribute Primary attribute key
     * @param string|null $fallback_attribute Optional fallback attribute key
     * @return string Attribute value, fallback value, or 'inherit'
     */
    private function get_attribute( $attribute_tuples, $attribute, $fallback_attribute = null ) {
        $result = isset( $attribute_tuples[ $attribute ] ) ? $attribute_tuples[ $attribute ] : '';

        if ( empty( $result ) && isset( $fallback_attribute ) ) {
            $result = isset( $attribute_tuples[ $fallback_attribute ] ) ? $attribute_tuples[ $fallback_attribute ] : '';
        }

        if ( empty( $result ) ) {
            return 'inherit';
        }
        return $result;
    }
}
