<?php
 
 /**
 * =============================================================================
 * @package			    Blue Raven (Free Version)
 * @Plugin URI			https://enterrahost.com/plugins/blue-raven
 * 
 * @Author			    EnterraHost
 * @Author URI			https://enterrahost.com
 * @License			    GPL-2.0-or-later
 *  
 * @Copyright			(c) 2025 EnterraHost
 * @File Description	WC related tools for My Products page
 * 
 * =============================================================================
 * 
 * || INDEX:
 * ||   - WP AJAX BLUE RAVEN MY PRODUCT
 * ||   - TAGS
 * ||   - PRODUCTS
 * ||   - CATEGORY
 * ||   - BRANDS
 * ||   - IMAGE ADD
 * ||   - SAVE TEXT
 * ||   - SAVE ATTRIBUTES
 * ||   - LOAD VARIATION EDIT BLOCK 
 * ||   - SAVE VARIATION
 * ||   - REMOVE VARATIONS
 * ||   - SAVE DRAFT
 * ||   - RELOAD VARIATION
 * ||   - REDO AND TRY AGAIN
 * || 
 * =============================================================================
 */

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

/*
============================================================
    WP AJAX BLUE RAVEN MY PRODUCT
============================================================
*/

add_action('wp_ajax_blue_raven_my_products', 'wp_ajax_blue_raven_my_products');

function wp_ajax_blue_raven_my_products() {
    
    $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';

    if (!wp_verify_nonce($nonce, 'blue_raven_my_products_nonce')) {
        BlueRaven_SendError("ERROR", "blue-raven/includes/admin-my-products.php", "wp_ajax_blue_raven_my_products", "Invalid nonce");
        wp_send_json_error('Invalid nonce');
    }
    
    ## =========== Action =========== ##
        
    $action = isset($_POST['subaction']) ? sanitize_text_field(wp_unslash($_POST['subaction'])) : '';

    BlueRaven_SendError("ERROR", "Delete", "action", $action);
    
/*
============================================================
    TAGS
============================================================
*/

    if ($action === 'get relavent tags') {
        $search = isset($_POST['context']) ? sanitize_text_field(wp_unslash($_POST['context'])) : '';
        
        $tags = get_terms(['taxonomy' => 'product_tag','name__like' => $search,'hide_empty' => false,'number' => 11]);
        $results = [];
        
        if (!is_wp_error($tags)) {
            $hasMore = count($tags) > 10;
            foreach (array_slice($tags, 0, 10) as $tag) {$results[] = ['id'   => $tag->slug,'text' => $tag->name];}        
            if ($hasMore) $results[] = ['id'   => 'no-add-tag','text' => 'More...'];
        }
        
        wp_send_json($results);
        
/*
============================================================
    PRODUCTS
============================================================
*/

    }else if ($action === 'search woocommerce products') {
        
        $search_term = isset($_POST['context']) ? sanitize_text_field(wp_unslash($_POST['context'])) : '';

        $args = array('post_type' => 'product','posts_per_page' => 10,'s' => $search_term,'post_status' => 'publish');
        $products = get_posts($args);
        $results = array();
        
        foreach ($products as $product) {
            $wc_product = wc_get_product($product->ID);
            $results[] = array('id' => $product->ID,'name' => $product->post_title,'sku' => $wc_product->get_sku(),'price' => wc_price($wc_product->get_price()));
        }
        
        wp_send_json($results);
    
/*
============================================================
    CATEGORY
============================================================
*/

    } elseif ($action === 'add category') { 
        
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We unslash $_POST['content'] here and manually sanitize individual values after. Everything is secure.
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];
        
        $name = sanitize_text_field($content[0]);
        $parent_slug = sanitize_text_field($content[1]);
        $parent_id = 0;

        if (!$name) wp_send_json_error(['message' => 'Category name is required'], 400);
        if ($parent_slug) {$parent_term = get_term_by('slug', $parent_slug, 'product_cat');if ($parent_term && !is_wp_error($parent_term)) { $parent_id = $parent_term->term_id; }}
    
        $result = wp_insert_term($name, 'product_cat', ['parent' => $parent_id ]);
    
        if (is_wp_error($result)) wp_send_json_error($result->get_error_message());
            
        ob_start();
        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-category-select-add.php';
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html,'message' => 'Category "' . esc_html($name) . '" added successfully!']);
        
        exit();
            
/*
============================================================
    BRANDS
============================================================
*/

    } elseif ($action === 'add brand') {  
        
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We unslash $_POST['content'] here and sanitize values manually below.
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];
        
        $brand_name = sanitize_text_field($content[0]);
        $parent_slug = sanitize_text_field($content[1]);
        $parent_id = 0;
        
        if (!$brand_name) wp_send_json_error(['message' => 'Brand name is required'], 400); 
        if ($parent_slug) {$parent_term = get_term_by('slug', $parent_slug, 'product_brand');if ($parent_term && !is_wp_error($parent_term)) { $parent_id = $parent_term->term_id; }}
        
        $result = wp_insert_term($brand_name,'product_brand', ['parent' => $parent_id,'slug' => sanitize_title($brand_name)]);
        
        if (is_wp_error($result)) wp_send_json_error($result->get_error_message());
        
        ob_start();
        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-brand-select-add.php';
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html,'message' => 'Brand "' . esc_html($name) . '" added successfully!']);
        
        exit();

/*
============================================================
    IMAGE ADD
============================================================
*/  

    } else if ($action === 'add image block') { include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-img-add.php';
    
    } else if ($action === 'save alt text') {
        
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We unslash and sanitize manually below.
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];

        $image_URL = esc_url_raw(isset($content[0]) ? $content[0] : '');
        $altText = sanitize_text_field(isset($content[1]) ? $content[1] : 0);

        $attachment_id = attachment_url_to_postid($image_URL);

        if ($attachment_id) {
            update_post_meta($attachment_id, '_wp_attachment_image_alt', $altText);
            wp_send_json_success([
                'message' => "Alt text updated successfully"
            ]);
        } else {
            wp_send_json_success([
                'message' => "Alt text updated successfully for {$image_URL}"
            ]);
        }
        
/*
============================================================
    SAVE TEXT
============================================================
*/
    
    } else if ($action === 'save long description') {
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We unslash and sanitize manually below.
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];

        $text_raw = isset($content[0]) ? $content[0] : '';
        $id_raw = isset($content[1]) ? $content[1] : 0;

        $text = wp_kses_post($text_raw);
        $id = intval($id_raw);

        global $wpdb;
        $table_name = $wpdb->prefix . 'BlueRavenProducts';

        $updated = $wpdb->update($table_name, ['description' => $text], ['id' => $id]);
        if ($updated !== false) {
            wp_send_json_success('Saved Long Description Draft');
        } else {
            wp_send_json_error('Error Saving Long Description Draft');
        }

    } else if ($action === 'save short description') {
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We unslash and sanitize manually below.
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];

        $text_raw = isset($content[0]) ? $content[0] : '';
        $id_raw  = isset($content[1]) ? $content[1] : 0;

        $text = wp_kses_post($text_raw);
        $id   = intval($id_raw);

        global $wpdb;
        $table_name = $wpdb->prefix . 'BlueRavenProducts';

        $updated = $wpdb->update($table_name, ['short_description' => $text], ['id' => $id]);
        if ($updated !== false) {
            wp_send_json_success('Saved Short Description Draft');
        } else {
            wp_send_json_error('Error Saving Short Description Draft');
        }

/*
============================================================
    SAVE ATTRIBUTES
============================================================
*/

    } elseif ($action === 'save attributes') {

    ## =========== Get raw JSON from POST safely =========== ##

        $raw_json = '';
        if ( isset( $_POST['content'][0] ) ) {
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            $raw_json = wp_unslash( $_POST['content'][0] ); 
            $raw_json = trim( $raw_json ); 
        }

        if ( $raw_json === '' ) wp_send_json_error( 'No content provided.' );

    ## =========== Decode JSON into array =========== ##

        $decoded_data = json_decode( $raw_json, true );

    ## =========== Validate JSON decode =========== ##

        if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $decoded_data ) ) wp_send_json_error( 'Invalid JSON: ' . json_last_error_msg() );

    ## =========== Extract and sanitize attributes =========== ##

        $attributes = [];
        if ( isset( $decoded_data['attributes'] ) && is_array( $decoded_data['attributes'] ) ) {
            $attributes = $decoded_data['attributes'];

            array_walk_recursive(
                $attributes,
                function ( &$value ) { if ( is_string( $value ) ) $value = sanitize_text_field( $value ); }
            );
        }

    ## =========== Sanitize and validate product ID =========== ##

        $pid = 0;
        if ( isset( $decoded_data['productId'] ) ) {
            $pid_raw = $decoded_data['productId'];
            $pid_sanitized = sanitize_text_field( (string) $pid_raw );
            if ( is_numeric( $pid_sanitized ) ) $pid = intval( $pid_sanitized );
        }

        if ( $pid <= 0 ) wp_send_json_error( 'Invalid product ID.' );

    ## =========== Update database =========== ##

        global $wpdb;
        $products_table_name = $wpdb->prefix . 'BlueRavenProducts';

        $result = $wpdb->update(
            $products_table_name,
            [ 'attributes_json' => wp_json_encode( $attributes ) ], 
            [ 'id' => $pid ],
            [ '%s' ],
            [ '%d' ]
        );

    ## =========== Return response =========== ##

        if ( $result === false ) wp_send_json_error( 'Database update failed.' );
        wp_send_json_success( 'Attributes have been saved.' );

/*
============================================================
    LOAD VARIATION EDIT BLOCK 
============================================================
*/

    } else if ($action === 'load variations edit block') {
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- manual unslash below
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];

        include BLUERAVEN_PLUGIN_DIR . 'templates/blocks/block-variations-edit.php';
        exit();
  
/*
============================================================
    SAVE VARIATION
============================================================
*/ 
    
    } else if ($action === 'save variation') {
        require_once BLUERAVEN_PLUGIN_DIR . 'includes/extras/my-product-save-variations.php';
        
        $content = isset($_POST['content']) ? array_map('sanitize_text_field', (array) wp_unslash($_POST['content'])) : [];

        if (isset($content[0])) {
            $decoded_data = json_decode($content[0], true);
            
            if (json_last_error() !== JSON_ERROR_NONE) {
                $data = sanitize_text_field($content[0]);
            } else {
                $data = http_build_query($decoded_data);
            }

            $saved = BlueRaven_saveVariations($data);

            if ($saved) {
                wp_send_json_success('Variation Edits Saved');
            } else {
                wp_send_json_error('Variation Edits Could Not Be Saved.');
            }
        } else {
            wp_send_json_error('No data received.');
        }

        exit();
    
/*
============================================================
    REMOVE VARATIONS
============================================================
*/ 
    } else if ($action === 'remove varation') {
        
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- manual unslash + sanitize below
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];

        $id = isset($content[0]) ? sanitize_text_field($content[0]) : '';
        $Pid = isset($content[1]) ? sanitize_text_field($content[1]) : '';

        global $wpdb;
        $table_name = $wpdb->prefix . 'BlueRavenProducts';

    ## =========== Get the existing CSV string =========== ##

        $existing_csv = $wpdb->get_var($wpdb->prepare("SELECT variations_CSV FROM $table_name WHERE ID = %d",$Pid));
        if (!$existing_csv) return;

    ## =========== Use memory stream to safely parse CSV =========== ##

        $rows = [];
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- opening php://temp memory stream, not a real file
        $fp = fopen('php://temp', 'r+');
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite -- writing to php://temp memory stream
        fwrite($fp, $existing_csv);
        rewind($fp);

        while (($row = fgetcsv($fp)) !== false) { if (isset($row[0]) && $row[0] != $id) $rows[] = $row; }
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- closing php://temp stream, not a real file
        fclose($fp);

    ## =========== Write back to CSV using memory stream =========== ##

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- opening php://temp memory stream, not a real file
        $fp = fopen('php://temp', 'r+');
        foreach ($rows as $row) { fputcsv($fp, $row);}
        rewind($fp);
        $updated_csv = stream_get_contents($fp);
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- closing php://temp stream, not a real file
        fclose($fp);

    ## =========== Update database =========== ##

        $wpdb->update($table_name,['variations_CSV' => trim($updated_csv)],['ID' => $Pid],['%s'],['%d']);
        wp_send_json_success('Row removed successfully.');
   
/*
============================================================
    SAVE DRAFT
============================================================
*/ 
    
    } else if ($action === 'save draft') {
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- serialized data; unslash before use
        $serialized_content = isset($_POST['content'][0]) ? wp_unslash($_POST['content'][0]) : '';

        require_once BLUERAVEN_PLUGIN_DIR . 'includes/extras/my-product-save-draft.php';
        BlueRaven_saveProductBR($serialized_content);

/*
============================================================
    RELOAD VARIATION
============================================================
*/ 
    
    } else if ($action === 'reload variation') {
        require_once BLUERAVEN_PLUGIN_DIR . 'extras/my-product-extras.php';  
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- manual unslash + sanitization below
        $content = isset($_POST['content']) ? wp_unslash($_POST['content']) : [];

        $param1 = isset($content[1]) ? sanitize_text_field($content[1]) : '';
        $param2 = isset($content[0]) ? sanitize_text_field($content[0]) : '';

        // If these are numeric IDs, you might prefer intval():
        echo wp_kses_post(BlueRaven_create_rows($param1, $param2));
        
    }else{
        echo("unknown item");
    }
    
    exit();
}

function BlueRaven_sanitize_attributes_array($array) {
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $array[$key] = BlueRaven_sanitize_attributes_array($value);
        } elseif (is_string($value)) {
            $array[$key] = sanitize_text_field($value); 
        }
    }
    return $array;
}