<?php
/**
 * The core plugin class for Trello API integration.
 *
 * This class handles all Trello API interactions including:
 * - Creating Trello cards from WooCommerce orders
 * - Managing card attributes (labels, due dates, checklists)
 * - Fetching boards and lists
 * - Evaluating order filters
 *
 * @since      1.0.0
 * @package    Wootrello
 * @subpackage Wootrello/includes
 * @author     javmah <jaedmah@gmail.com>
 */

require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-wootrello-helpers.php';

class Wootrello_Trello_API {

    /** @var Wootrello_Helpers Helper class instance */
    protected $helpers;

    /** @var string Trello Application Key */
    private $key = '7385fea630899510fd036b6e89b90c60';

    /** @var string Base API URL */
    private $api_base = 'https://api.trello.com/1';

    /**
     * Initialize the class and set its properties.
     *
     * @since 1.0.0
     */
    public function __construct() {
        $this->helpers = new Wootrello_Helpers;
    }

    /**
     * Primary Orchestrator: Creates a Trello card for a WooCommerce order.
     *
     * This is the main method that coordinates the entire card creation process:
     * 1. Checks for duplicate cards
     * 2. Validates API credentials
     * 3. Fetches and validates settings
     * 4. Evaluates filters
     * 5. Verifies permissions
     * 6. Builds card data (title & description)
     * 7. Creates card via API
     * 8. Adds checklists and attributes
     * 9. Finalizes and logs
     *
     * @since 1.0.0
     * @param string $order_status The status of the order (e.g., 'new_order', 'processing')
     * @param array  $order_info   Array containing all order information
     * @return array Array with [boolean success, string message]
     */
    public function wootrello_create_trello_card($order_status = "", $order_info = array()) {

        $order_id = isset($order_info['orderID']) ? $order_info['orderID'] : 0;

        // ==========================================
        // STEP 1: Check for Duplicate Cards
        // ==========================================
        if ($this->check_duplicate_card($order_id, $order_status)) {
             return array(FALSE, "Stop duplicate card for status '" . $order_status . "' - created too recently!");
        }

        // ==========================================
        // STEP 2: Validate API Key
        // ==========================================
        $token = get_option("wootrello_trello_API");
        if (empty($token)) {
            $this->helpers->wootrello_log(__METHOD__, 705, "ERROR: User API key is empty");
            return array(FALSE, "No API key found!");
        }

        // ==========================================
        // STEP 3: Fetch & Validate Settings
        // ==========================================
        $integration = $this->get_integration_settings($order_status);
        if (!$integration) {
            return array(FALSE, "No settings saved for status: " . $order_status);
        }

        $settings = $integration['settings']; // Board, List, Labels, Due Date, etc.
        $card_config = $integration['card_config']; // Content formatting checkboxes

        // ==========================================
        // STEP 4: Evaluate Filters
        // ==========================================
        if (!$this->wootrello_evaluate_filters($order_info, $settings)) {
            $this->helpers->wootrello_log(__METHOD__, 200, "Filter Blocked: Order #{$order_id}");
            return false;
        }

        // ==========================================
        // STEP 5: Verify Permissions (Freemius)
        // ==========================================
        if (!wootrello_freemius()->can_use_premium_code() && $order_status != 'new_order') {
            return array(FALSE, "Status change automation is a Professional feature.");
        }

        // ==========================================
        // STEP 6: Build Card Data
        // ==========================================
        $title = $this->prepare_card_title($order_info, $card_config);
        $description = $this->prepare_card_description($order_info, $card_config);

        // ==========================================
        // STEP 7: Create Card via API
        // ==========================================
        $card_id = $this->api_create_card($title, $description, $settings['trello_list'], $token);

        if (!$card_id) {
            $this->helpers->wootrello_write_status_on_order_meta($order_id, "wootrello_error");
            return array(FALSE, "Trello API error or empty response.");
        }

        // ==========================================
        // STEP 8: Post-Creation Actions
        // ==========================================
        $this->process_card_checklist($card_id, $order_info, $card_config, $token);
        $this->apply_card_attributes($card_id, $settings, $token);

        // ==========================================
        // STEP 9: Finalize
        // ==========================================
        $this->helpers->wootrello_write_status_on_order_meta($order_id, $order_status);
        $this->helpers->wootrello_log(__METHOD__, 200, 'SUCCESS: card created successfully!');

        return array('TRUE', "Card created successfully!");
    }

    /* ==========================================================================
       DATA PREPARATION METHODS
       ========================================================================== */

    /**
     * Constructs the card title based on configuration.
     *
     * Builds the title from multiple components:
     * - Order ID
     * - Date (in various formats)
     * - Customer name (premium)
     * - Order total (premium)
     * - Custom meta fields (premium, with HPOS compatibility)
     *
     * The order of these elements can be configured via settings.
     *
     * @since 1.0.0
     * @param array $order_info   Order data array
     * @param array $card_config  Card configuration settings
     * @return string Formatted card title
     */
    private function prepare_card_title($order_info, $card_config) {
        $parts = array(
            'base' => '',
            'meta' => ''
        );

        // --- Base Title Parts (ID, Date, Customer, Total) ---
        $base_parts = array();
        
        // Add Order ID
        if (!empty($card_config["order_id_in_title"])) {
            $base_parts[] = '#' . $order_info["orderID"];
        }
        
        // Add Date in specified format
        if (!empty($card_config["date"])) {
            $format = isset($card_config['date_formate']) ? $card_config['date_formate'] : 'us';
            switch ($format) {
                case 'uk': 
                    $base_parts[] = '#' . date("d/m/Y"); // 31/01/2025
                    break;
                case 'uk_alphabet': 
                    $base_parts[] = '#' . date("j F Y"); // 3 February 2025
                    break;
                default: 
                    $base_parts[] = '#' . date("Y/m/d"); // 2025/01/31
                    break;
            }
        }

        // Premium Features: Customer Name and Order Total
        if (wootrello_freemius()->can_use_premium_code()) {
            if (!empty($card_config["customer_name_in_title"])) {
                $base_parts[] = '#' . $order_info["billing_first_name"] . " " . $order_info["billing_last_name"];
            }
            if (!empty($card_config["order_total_in_title"])) {
                $base_parts[] = '#' . $order_info["total"];
            }
        }

        $parts['base'] = implode(' ', $base_parts);

        // --- Unified Meta Data Part (HPOS Compatible) ---
        if (wootrello_freemius()->can_use_premium_code()) {
            // Try new unified key first
            $parts['meta'] = $this->extract_meta_for_title($order_info['orderID'], $card_config, 'orderTitleMeta');

            // Migration Fallback: Check old legacy key if new key is empty
            if (empty($parts['meta'])) {
                $parts['meta'] = $this->extract_meta_for_title($order_info['orderID'], $card_config, 'orderTitlePostMeta');
            }
        }

        // --- Determine Final Ordering ---
        $meta_pos = isset($card_config["order_meta_position"]) ? $card_config["order_meta_position"] : '';

        if ($meta_pos === "order_meta_before_default_fields") {
            // Custom Fields first, then Order ID/Date/Name
            $ordered_string = $parts['meta'] . " " . $parts['base'];
        } else {
            // Order ID/Date/Name first, then Custom Fields
            $ordered_string = $parts['base'] . " " . $parts['meta'];
        }

        return trim($ordered_string);
    }

    /**
     * Helper to extract meta keys for title string.
     *
     * This method is HPOS compatible - it uses WC_Order::get_meta()
     * which automatically works with both custom tables and post_meta.
     *
     * @since 3.1.0
     * @param int    $order_id    WooCommerce order ID
     * @param array  $config      Card configuration array
     * @param string $config_key  Key name in config ('orderTitleMeta' or 'orderTitlePostMeta')
     * @return string Concatenated meta values prefixed with #
     */

	private function extract_meta_for_title($order_id, $config, $config_key) {
		if (empty($config[$config_key]) || !is_array($config[$config_key])) return '';
		
		$output = '';
		foreach ($config[$config_key] as $key) {
			$val = $this->get_meta_direct($order_id, $key);
			if ($val !== '') {
				$output .= ' #' . $val;
			}
		}
		return $output;
	}


	/**
	 * Fetches meta data directly from DB to bypass WooCommerce "internal key" restrictions.
	 * Robustly handles both Legacy Postmeta and HPOS Tables.
	 */
	private function get_meta_direct($order_id, $key) {
		global $wpdb;
		$key = trim($key);
		if (empty($key) || empty($order_id)) return '';

		// Determine Table & Column (Check for HPOS compatibility)
		$table = $wpdb->prefix . 'postmeta';
		$column = 'post_id';

		if (class_exists('Automattic\WooCommerce\Utilities\OrderUtil')) {
			if (method_exists('Automattic\WooCommerce\Utilities\OrderUtil', 'custom_orders_table_usage_is_enabled')) {
				if (\Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled()) {
					$table = $wpdb->prefix . 'wc_orders_meta';
					$column = 'order_id';
				}
			}
		}

		$value = $wpdb->get_var($wpdb->prepare(
			"SELECT meta_value FROM $table WHERE $column = %d AND meta_key = %s LIMIT 1",
			$order_id,
			$key
		));

		if ($value === null) return '';

		$val = maybe_unserialize($value);
		// Convert arrays/objects to string for Trello display
		return (is_array($val) || is_object($val)) ? json_encode($val) : $val;
	}

    /**
     * Constructs the card description (body).
     *
     * Builds a comprehensive description including:
     * - Basic order info (ID, status, URL)
     * - Customer details (name, email, phone, note)
     * - Addresses (billing & shipping)
     * - Payment & shipping methods
     * - Order totals and discounts
     * - Product list with details
     * - Custom meta fields (HPOS compatible)
     * - Previous order history
     * - Third-party plugin fields (Checkout Field Editor)
     *
     * @since 1.0.0
     * @param array $order_info   Order data array
     * @param array $card_config  Card configuration settings
     * @return string Formatted card description
     */
    private function prepare_card_description($order_info, $card_config) {
        $desc = "";

        // Helper function to format lines cleanly
        // $add_line = function($label, $value, $newline = true) {
        //     if (empty($value)) return "";
        //     return ($newline ? "\n" : ' ') . "**{$label}:** " . $value;
        // };

		$add_line = function($label, $value, $newline = true) {
			$value = (string) $value; // force string
			return ($newline ? "\n" : ' ') . "**{$label}:** " . $value;
		};



        // ==========================================
        // Basic Order Information
        // ==========================================
        $desc .= $add_line("Order ID", $order_info["orderID"]);
        $desc .= $add_line("Order status", $order_info["status"]);
        
        // Premium: Order Edit URL
        if (wootrello_freemius()->can_use_premium_code()) {
            if (!empty($card_config["order_url"])) {
                $desc .= $add_line("Order URL", $order_info["edit_order_url"]);
            }
        }

        // ==========================================
        // Customer Information
        // ==========================================
        if (!empty($card_config["customer_name"])) {
             $desc .= $add_line("Customer name", $order_info["billing_first_name"] . " " . $order_info["billing_last_name"]);
        }

	
        // Premium: Extended Customer Details
        if (wootrello_freemius()->can_use_premium_code()) {
            if (!empty($card_config["customer_note"])) {
                $desc .= $add_line("Customer note", $order_info["customer_note"]);
            }
            if (!empty($card_config["billing_email"])) {
                $desc .= $add_line("Billing email", $order_info["billing_email"]);
            }
            if (!empty($card_config["billing_phone"])) {
                $desc .= $add_line("Billing phone", $order_info["billing_phone"]);
            }
        }

        // ==========================================
        // Addresses
        // ==========================================
        if (!empty($card_config["billing_address"])) {
            $desc .= "\n**Billing address:**\n" . $this->format_address($order_info, 'billing');
        }
        if (!empty($card_config["shipping_address"])) {
            $desc .= "\n**Shipping address:**\n" . $this->format_address($order_info, 'shipping');
        }

        // ==========================================
        // Shipping & Payment Details
        // ==========================================
        // Premium: Extended Shipping Details
        if (wootrello_freemius()->can_use_premium_code()) {
            if (!empty($card_config["shipping_method"])) {
                $desc .= $add_line("Shipping method", $order_info["shipping_method"]);
            }
            if (!empty($card_config["shipping_total"])) {
                $desc .= $add_line("Shipping total", $order_info["shipping_total"]);
            }
            if (!empty($card_config["discount_total"])) {
                $desc .= $add_line("Discount total", $order_info["discount_total"]);
            }
            if (!empty($card_config["cart_items_weight"])) {
                $desc .= $add_line("Cart items weight", $order_info["cart_items_weight"]);
            }
        }

        // Product Categories
        if (!empty($card_config["product_categories"])) {
            $desc .= $add_line("Product categories", $order_info["product_categories"]);
        }

        // Payment Method
        if (!empty($card_config["payment_method"])) {
            $desc .= $add_line("Payment method", $order_info["payment_method"]);
        }

        // Order Total
        if (!empty($card_config["order_total"])) {
            $desc .= $add_line("Order total", $order_info["total"] . " " . $order_info['currency']);
        }

        // ==========================================
        // Order Items List
        // ==========================================
        if (get_option('wootrello_include_products_in_card') == 1 && !empty($order_info['items'])) {
            $desc .= "\n\n----\n\n**Order Items:**\n";
            $i = 1;
            foreach ($order_info['items'] as $item) {
                $line = "\n{$i}. ";
                
                // Product ID
                if (!empty($card_config['product_id'])) {
                    $line .= "ID: " . $item['product_id'] . " ";
                }
                
                // Product Name as Link
                $p_name = $item['product_name'];
                $p_link = get_permalink($item['product_id']);
                $line .= "[{$p_name}]({$p_link}) ";

                // Product SKU (Premium)
                if (wootrello_freemius()->can_use_premium_code()) {
                    if (!empty($card_config['product_sku']) && !empty($item['product_sku'])) {
                        $line .= "SKU: " . $item['product_sku'] . " ";
                    }
                }

                // Product Quantity
                if (!empty($card_config['product_qty'])) {
                    $line .= "Qty: " . $item['qty'] . " ";
                }

                // Premium: Weight and Price
                if (wootrello_freemius()->can_use_premium_code()) {
                    if (!empty($card_config['product_weight']) && !empty($item['product_weight'])) {
                        $line .= "Weight: " . $item['product_weight'] . "kg ";
                    }
                    if (!empty($card_config['product_qty_price']) && !empty($item['product_qty_price'])) {
                        $line .= "Price: " . $item['product_qty_price'] . " ";
                    }
                }
                
                $desc .= $line;
                $i++;
            }
        }

        // ==========================================
        // Custom Meta Fields (HPOS Compatible)
        // ==========================================
        if (wootrello_freemius()->can_use_premium_code()) {
            $meta_output = "";

            // Try new unified key first
            if (!empty($card_config['orderBodyMeta'])) {
                $meta_output .= $this->extract_unified_meta_content($order_info['orderID'], $card_config['orderBodyMeta']);
            } 
            // Fallback for migration: check old separate keys
            else {
                if (!empty($card_config['orderMetaKeys'])) {
                    $meta_output .= $this->extract_unified_meta_content($order_info['orderID'], $card_config['orderMetaKeys']);
                }
                if (!empty($card_config['orderPostMetaKeys'])) {
                    $meta_output .= $this->extract_unified_meta_content($order_info['orderID'], $card_config['orderPostMetaKeys']);
                }
            }

            if (!empty($meta_output)) {
                $desc .= "\n\n----\n\n**Custom Fields:**\n" . $meta_output;
            }
        }

        // ==========================================
        // Previous Orders History (Premium)
        // ==========================================
        if (wootrello_freemius()->can_use_premium_code()) {
            if (!empty($card_config["previous_orders"])) {
                $previous_orders = $this->helpers->wootrello_user_previous_orders($order_info["billing_email"]);
                if ($previous_orders[0] && !empty($previous_orders[2])) {
                    $desc .= "\n\n----\n\n**Previous orders:** " . $previous_orders[2];
                }
            }
        }

        // ==========================================
        // Third-Party Plugin: Checkout Field Editor
        // ==========================================
        if (wootrello_freemius()->can_use_premium_code()) {
            $woo_checkout_field_editor_fields = $this->helpers->wootrello_woo_checkout_field_editor_pro_fields();
            
            if (!empty($card_config["checkout_field_editor"]) && $woo_checkout_field_editor_fields[0]) {
                $desc .= "\n\n----\n";
                
                foreach ($woo_checkout_field_editor_fields[1] as $key => $arr) {
                    $label = (!empty($arr['label'])) ? $arr['label'] : false;
                    $value = false;
                    
                    if (isset($order_info['orderID'], $key)) {
                        $meta_value = get_post_meta($order_info['orderID'], $key, true);
                        if (!empty($meta_value)) {
                            $value = $meta_value;
                        }
                    }
                    
                    if ($label && $value) {
                        $desc .= "\n**" . $label . ":** " . $value;
                    }
                }
            }
        }

        return $desc;
    }

    /**
     * Unified Meta Extractor for Description.
     *
     * Works for both Legacy post_meta and HPOS custom tables automatically
     * using WC_Order::get_meta() which handles both storage methods.
     *
     * @since 3.1.0
     * @param int   $order_id   WooCommerce order ID
     * @param array $meta_keys  Array of meta key names to extract
     * @return string Formatted meta content with labels
    */
	private function extract_unified_meta_content($order_id, $meta_keys) {
		if (empty($meta_keys) || !is_array($meta_keys)) return "";
		
		$output = "";
		foreach ($meta_keys as $key) {
			$val = $this->get_meta_direct($order_id, $key);
			// Show -- if value is empty so the user knows the field exists but is blank
			$display_val = ($val === '') ? '' : $val;
			$output .= "\n**{$key}:** {$display_val}";
		}
		return $output;
	}

    /**
     * Format address into multi-line string.
     *
     * @since 1.0.0
     * @param array  $info Order info array
     * @param string $type Address type ('billing' or 'shipping')
     * @return string Formatted address with line breaks
     */
    private function format_address($info, $type) {
        $parts = array(
            $info["{$type}_address_1"],
            isset($info["{$type}_address_2"]) ? $info["{$type}_address_2"] : '',
            $info["{$type}_city"],
            $info["{$type}_state"],
            $info["{$type}_postcode"],
            $info["{$type}_country"]
        );
        return implode("\n", array_filter($parts));
    }

    /* ==========================================================================
       API INTERACTION METHODS
       ========================================================================== */

    /**
     * Sends the create card request via POST Body.
     *
     * Uses wp_remote_post with body array to safely handle special characters
     * like # and & in the title and description.
     *
     * @since 1.0.0
     * @param string $title       Card title
     * @param string $description Card description
     * @param string $list_id     Trello list ID
     * @param string $token       User's Trello token
     * @return string|false Card ID on success, false on failure
     */
    private function api_create_card($title, $description, $list_id, $token) {
        $url = $this->api_base . '/cards';
        
        $body = array(
            'name'           => $title,
            'desc'           => $description,
            'pos'            => 'top',
            'idList'         => $list_id,
            'keepFromSource' => 'all',
            'key'            => $this->key,
            'token'          => $token
        );

        $response = wp_remote_post($url, array(
            'body' => $body
        ));

        if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200) {
            $this->helpers->wootrello_log(__METHOD__, 716, 'API Error: ' . json_encode($response));
            return false;
        }

        $body_response = json_decode(wp_remote_retrieve_body($response), true);
        return isset($body_response['id']) ? $body_response['id'] : false;
    }

    /**
     * Process Card Checklist - Creates checklist and adds order items.
     *
     * Creates a "Order Items" checklist on the card and populates it
     * with all order line items including optional details like SKU,
     * quantity, weight, and price.
     *
     * @since 1.0.0
     * @param string $card_id     Trello card ID
     * @param array  $order_info  Order data array
     * @param array  $card_config Card configuration settings
     * @param string $token       User's Trello token
     * @return void
     */
    private function process_card_checklist($card_id, $order_info, $card_config, $token) {
        if (empty($order_info['items'])) return;

        // ==========================================
        // Step 1: Create Checklist
        // ==========================================
        $url = "{$this->api_base}/cards/{$card_id}/checklists";
        $response = wp_remote_post($url, array(
            'body' => array(
                'name'  => 'Order Items',
                'pos'   => 'top',
                'key'   => $this->key,
                'token' => $token
            )
        ));
        
        $body = json_decode(wp_remote_retrieve_body($response), true);
        if (empty($body['id'])) {
            $this->helpers->wootrello_log(__METHOD__, 714, "Checklist creation failed");
            return;
        }

        $checklist_id = $body['id'];
        $i = 1;

        // ==========================================
        // Step 2: Add Items to Checklist
        // ==========================================
        foreach ($order_info['items'] as $item) {
            $name_parts = array();
            
            // Serial Number
            if (!empty($card_config["product_serial_number"])) {
                $name_parts[] = "$i -";
            }
            
            // Product ID
            if (!empty($card_config["product_id"])) {
                $name_parts[] = "{$item['product_id']} -";
            }
            
            // Product Name as Link
            $name_parts[] = '[' . $item['product_name'] . '](' . get_permalink($item['product_id']) . ')';
            
            // Quantity
            if (!empty($card_config["product_qty"])) {
                $name_parts[] = "qty: " . $item['qty'];
            }
            
            // Premium Features
            if (wootrello_freemius()->can_use_premium_code()) {
                // SKU
                if (!empty($card_config["product_sku"]) && !empty($item['product_sku'])) {
                    $name_parts[] = "sku: " . $item['product_sku'];
                }
                
                // Weight
                if (!empty($card_config["product_weight"]) && !empty($item['product_weight'])) {
                    $name_parts[] = "weight: " . $item['product_weight'] . 'kg';
                }
                
                // Price
                if (!empty($card_config["product_qty_price"]) && !empty($item['product_qty_price'])) {
                    $name_parts[] = "price: " . $item['product_qty_price'];
                }
            }

            $item_name = implode(' ', $name_parts);
            
            // Create check item
            $item_url = "{$this->api_base}/checklists/{$checklist_id}/checkItems";
            wp_remote_post($item_url, array(
                'body' => array(
                    'name'    => $item_name,
                    'pos'     => 'top',
                    'checked' => 'false',
                    'key'     => $this->key,
                    'token'   => $token
                )
            ));
            
            $i++;
        }
    }

    /**
     * Apply Card Attributes - Labels and Due Dates.
     *
     * Applies optional card attributes like label colors and due dates
     * based on the integration settings. Only available in premium version.
     *
     * @since 1.0.0
     * @param string $card_id  Trello card ID
     * @param array  $settings Integration settings
     * @param string $token    User's Trello token
     * @return void
     */
    private function apply_card_attributes($card_id, $settings, $token) {
        if (!wootrello_freemius()->can_use_premium_code()) return;

        $payload = array();
        
        // Add Label Color
        if ( ! empty( $settings['trello_label_colour'] ) ) {
            $payload['idLabels'] = array($settings['trello_label_colour']);
        }
        
        // Add Due Date
        if ( ! empty( $settings['trello_due_date'] ) ) {
            $payload['due'] = $this->helpers->DueDateCalc($settings['trello_due_date']);
        }

        if (empty($payload)) return;

        // Send Update Request
        $url = "{$this->api_base}/cards/{$card_id}?key={$this->key}&token={$token}";
        wp_remote_request($url, array(
            'method' => 'PUT',
            'headers' => array('Content-Type' => 'application/json'),
            'body' => json_encode($payload)
        ));
    }

    /* ==========================================================================
       UTILITY METHODS
       ========================================================================== */

    /**
     * Get integration settings from database.
     *
     * Retrieves saved integration configuration for a specific order status
     * from the custom post type 'wootrello'.
     *
     * @since 2.0.0
     * @param string $status Order status identifier
     * @return array|false Array with 'settings' and 'card_config' keys, or false
     */
    private function get_integration_settings($status) {
        global $wpdb;
        $saved = $wpdb->get_results( 
            $wpdb->prepare("SELECT * FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'wootrello' LIMIT 1", 'wootrello_' . $status)
        );

        if (empty($saved) || empty($saved[0]->post_excerpt) || $saved[0]->post_status != 'publish') {
            return false;
        }

        $settings = json_decode($saved[0]->post_excerpt, TRUE);
        $card_config = json_decode($saved[0]->post_content, TRUE);

        if (empty($settings['trello_board']) || empty($settings['trello_list'])) {
            return false;
        }

        return array('settings' => $settings, 'card_config' => $card_config);
    }

    /**
     * Check for duplicate card creation.
     *
     * Prevents creating multiple cards for the same order status
     * within a 120-second window to avoid duplicate API calls.
     *
     * @since 1.0.0
     * @param int    $order_id WooCommerce order ID
     * @param string $status   Order status
     * @return bool True if duplicate detected, false otherwise
     */
    private function check_duplicate_card($order_id, $status) {
        $meta = get_post_meta($order_id, 'wootrello_status', TRUE);
        if ($meta && isset($meta[$status]) && is_array($meta[$status])) {
            $last_time = end($meta[$status]);
            if ((current_time('timestamp') - $last_time) < 120) {
                return true;
            }
        }
        return false;
    }

    /**
     * Get Trello boards for authenticated user.
     *
     * Fetches all open boards from Trello API for the authenticated user.
     *
     * @since 2.0.0
     * @param string $token User's Trello API token
     * @return array [response_code, boards_array] where boards_array is [id => name]
     */
    public function wootrello_trello_boards($token = '') {
        if (empty($token)) {
            return array(0, "ERROR: Empty trello token");
        }
        
        $url = 'https://api.trello.com/1/members/me/boards?&filter=open&key=' . $this->key . '&token=' . $token;
        $trello_returns = wp_remote_get($url, array());
        $boards = array();
        
        if (!is_wp_error($trello_returns) && isset($trello_returns['response']['code'], $trello_returns['body']) && $trello_returns['response']['code'] == 200) {
            foreach (json_decode($trello_returns['body'], TRUE) as $key => $value) {
                $boards[$value['id']] = $value['name'];
            }
            return array($trello_returns['response']['code'], $boards);
        } else {
            $this->helpers->wootrello_log('wootrello_trello_boards', 702, 'ERROR: ' . json_encode($trello_returns, TRUE));
            return array(410, array());
        }
    }

    /**
     * Get lists for a specific Trello board.
     *
     * Fetches all open lists for a given board ID.
     *
     * @since 2.0.0
     * @param string $token       User's Trello API token
     * @param string $board_id    Trello board ID
     * @param string $callingFunc Calling function name for logging
     * @return array [response_code, lists_array] where lists_array is [id => name]
     */
    public function wootrello_board_lists($token = '', $board_id = '', $callingFunc = '') {
        if (empty($token) || empty($board_id)) {
            return array(420, 'ERROR: Token or Board id is Empty!');
        }
        
        $url = 'https://api.trello.com/1/boards/' . $board_id . '/lists?filter=open&key=' . $this->key . '&token=' . $token;
        $trello_returns = wp_remote_get($url, array());
        $lists = array();
        
        if (isset($trello_returns['response']['code'], $trello_returns['body']) && $trello_returns['response']['code'] == 200) {
            foreach (json_decode($trello_returns['body'], TRUE) as $key => $value) {
                $lists[$value['id']] = $value['name'];
            }
        } else {
            $this->helpers->wootrello_log('wootrello_board_lists >> ' . $callingFunc, 703, 'ERROR: ' . json_encode($trello_returns, TRUE));
        }
        
        return array($trello_returns['response']['code'], $lists);
    }

    /**
     * Get Trello Board Labels.
     * * @since    3.0.0
     * @param    string    $access_token    Trello Access Token (Token).
     * @param    string    $board_id        The ID of the Trello Board.
     * @return   array                      An array containing the status code and label data.
     */
    public function wootrello_board_labels( $access_token, $board_id ) {
        # Check for empty values
        if ( empty( $access_token ) || empty( $board_id ) ) {
            return array( 400, "ERROR: Access token or Board ID is missing." );
        }

        # Trello API Endpoint for Labels
        # Note: Ensure $this->key (the App Key) is defined in this class.
        $url = "https://api.trello.com/1/boards/" . $board_id . "/labels?key=" . $this->key . "&token=" . $access_token;

        # Perform the Request
        $response = wp_remote_get( $url );

        # Check for WordPress Errors
        if ( is_wp_error( $response ) ) {
            return array( 500, "ERROR: Request failed." );
        }

        $body = wp_remote_retrieve_body( $response );
        $data = json_decode( $body, true );

        # Check for Trello API Errors
        if ( isset( $data['error'] ) || ! is_array( $data ) ) {
            return array( 401, "ERROR: Unauthorized or Invalid Board ID." );
        }

        # Prepare labels for the dropdown (ID => Name and Color)
        $labels = array();
        foreach ( $data as $label ) {
            $label_name = ! empty( $label['name'] ) ? $label['name'] : 'Unnamed Label';
            $labels[$label['id']] = $label_name . " (" . $label['color'] . ")";
        }

        return array( 200, $labels );
    }



    /**
     * Evaluates if an order matches the defined filters.
     *
     * This method checks if an order should trigger card creation based on
     * configured filters. Filters can check various order properties like:
     * - Order total, email, payment method, currency
     * - Item count, discount, shipping details
     * - Product IDs, names, SKUs, categories
     *
     * Filter strategy can be:
     * - 'ALL': All filters must match (AND logic)
     * - 'ANY': At least one filter must match (OR logic)
     *
     * @since 3.3.1
     * @param array $order_info Order data array containing all order properties
     * @param array $settings   Saved settings containing 'filters' and 'filter_strategy'
     * @return bool True if order matches filters (allow), false otherwise (block)
     */
    private function wootrello_evaluate_filters($order_info, $settings) {
        // ==========================================
        // Step 1: No Filters = Allow Everything
        // ==========================================
        if (!isset($settings['filters']) || empty($settings['filters'])) {
            return true;
        }

        // ==========================================
        // Step 2: Validate Input Data
        // ==========================================
        if (empty($order_info) || !is_array($order_info)) {
            $this->helpers->wootrello_log('wootrello_evaluate_filters', 720, 'ERROR: order_info is empty');
            return false;
        }

        $filters = $settings['filters'];
        $strategy = isset($settings['filter_strategy']) ? $settings['filter_strategy'] : 'ALL';
        $results = array();

        // ==========================================
        // Step 3: Evaluate Each Filter
        // ==========================================
        foreach ($filters as $filter) {
            // Skip invalid filter rows
            if (!isset($filter['field'], $filter['condition'], $filter['value'])) {
                continue;
            }

            $field = $filter['field'];
            $condition = $filter['condition'];
            // Normalize inputs: trim whitespace, lowercase for case-insensitive comparison
            $val_saved = strtolower(trim((string)$filter['value']));
            $val_order = '';

            // Map simple fields directly from $order_info keys
            $direct_map = array(
                'total'             => 'total',
                'billing_email'     => 'billing_email',
                'payment_method'    => 'payment_method',
                'currency'          => 'currency',
                'item_count'        => 'item_count',
                'total_discount'    => 'total_discount',
                'shipping_country'  => 'shipping_country',
                'shipping_city'     => 'shipping_city',
                'billing_state'     => 'billing_state',
                'billing_phone'     => 'billing_phone',
                'shipping_method'   => 'shipping_method',
                'product_category'  => 'product_categories',
            );

            // Get value from direct mapping
            if (array_key_exists($field, $direct_map)) {
                $key = $direct_map[$field];
                $val_order = isset($order_info[$key]) ? $order_info[$key] : '';
            }
            // Handle Product Items (Loop through items array)
            elseif (in_array($field, array('product_id', 'product_name', 'product_sku'))) {
                $collected = array();
                if (isset($order_info['items']) && is_array($order_info['items'])) {
                    foreach ($order_info['items'] as $item) {
                        if ($field === 'product_id' && isset($item['product_id'])) {
                            $collected[] = $item['product_id'];
                        } elseif ($field === 'product_name' && isset($item['product_name'])) {
                            $collected[] = $item['product_name'];
                        } elseif ($field === 'product_sku' && isset($item['product_sku'])) {
                            $collected[] = $item['product_sku'];
                        }
                    }
                }
                $val_order = implode(',', array_unique($collected));
            }
            else {
                // Unknown field, skip
                continue;
            }

            // Ensure order value is a string before processing
            $val_order = strtolower(trim((string)$val_order));
            $match = false;

            // Numeric conditions require both values to be numeric
            $numeric_conditions = array('greater_than', 'less_than', 'greater_than_equal', 'less_than_equal');

            // Safety Check: If doing math comparison, both values MUST be numeric
            if (in_array($condition, $numeric_conditions) && (!is_numeric($val_order) || !is_numeric($val_saved))) {
                $match = false;
            } else {
                // Evaluate condition
                switch ($condition) {
                    case 'equals':
                        $match = ($val_order == $val_saved);
                        break;
                    case 'not_equals':
                        $match = ($val_order != $val_saved);
                        break;
                    case 'greater_than':
                        $match = ((float)$val_order > (float)$val_saved);
                        break;
                    case 'less_than':
                        $match = ((float)$val_order < (float)$val_saved);
                        break;
                    case 'greater_than_equal':
                        $match = ((float)$val_order >= (float)$val_saved);
                        break;
                    case 'less_than_equal':
                        $match = ((float)$val_order <= (float)$val_saved);
                        break;
                    case 'contains':
                        // Ensure empty search string doesn't result in a true match
                        $match = ($val_saved !== '' && strpos($val_order, $val_saved) !== false);
                        break;
                    case 'not_contains':
                        // If saved value is empty, consider it as "does not contain anything specific"
                        $match = ($val_saved === '' || strpos($val_order, $val_saved) === false);
                        break;
                }
            }

            $results[] = $match;
        }

        // ==========================================
        // Step 4: Apply Filter Strategy
        // ==========================================
        if (empty($results)) {
            return true; // No valid filters to evaluate
        }

        if ($strategy === 'ANY') {
            // OR logic: At least one filter must match
            return in_array(true, $results, true);
        } else {
            // ALL logic (default): All filters must match
            return !in_array(false, $results, true);
        }
    }

}