<?php

use Atum\Suppliers\Suppliers;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

/**
 * Render product editor page
 */
function mdspbe_render_main_plugin_page() {

    // Security check
    if ( ! isset( $_GET['mdspbe_filter_action_nonce'] ) || 
        ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['mdspbe_filter_action_nonce'] ) ), 'mdspbe_filter_action' ) ) {
        
        $limit = 50;
        $page = 1;

        $args = [
            'page_number' => $page,
            'limit' => $limit,
            's' => '',
            'order' => 'DESC',
            'orderby' => 'ID',
            'status' => '',
            'product_category_id' => '',
            'product_tag_id' => '',
            'stock_status' => '',
            'visibility' => '',
        ];
        
        
        $args = apply_filters( 'mdspbe_product_filter_args', $args );

        $count = mdspbe_count_products( $args );
        $pages = ceil( $count / $limit );

        // Query the first page if the original page doesn't exist
        if ( $page > $pages ) {
            $args['page'] = 1;
        }
    } else {

        $filters_args = [];
        $args = [];

        $page = isset( $_GET['page_number'] ) ? absint( wp_unslash( $_GET['page_number'] ) ) : 1;
        $args['page_number'] = $page;

        $limit = isset( $_GET['limit'] ) ? absint( wp_unslash( $_GET['limit'] ) ) : 50;
        $limit = max( 5, $limit );
        $args['limit'] = $limit;

        $search = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
        $args['s'] = $search;

        $status = isset( $_GET['status'] ) ? sanitize_text_field( wp_unslash( $_GET['status'] ) ) : '';
        $args['status'] = $status;

        $cat_id = isset( $_GET['product_category_id'] ) ? absint( wp_unslash( $_GET['product_category_id'] ) ) : '';
        $args['product_category_id'] = $cat_id;

        $tag_id = isset( $_GET['product_tag_id'] ) ? absint( wp_unslash( $_GET['product_tag_id'] ) ) : '';
        $args['product_tag_id'] = $tag_id;

        $st_status = isset( $_GET['stock_status'] ) ? sanitize_text_field( wp_unslash( $_GET['stock_status'] ) ) : '';
        $args['stock_status'] = $st_status;

        $visibility = isset( $_GET['visibility'] ) ? sanitize_text_field( wp_unslash( $_GET['visibility'] ) ) : '';
        $args['visibility'] = $visibility;

        $order = isset( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : 'DESC';
        $args['order'] = $order;

        $orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : 'ID';
        $args['orderby'] = $orderby;

        $product_attrs = isset( $_GET['product_attrs'] ) ? $_GET['product_attrs'] : [];
    
        foreach ( $product_attrs as $attr_name => $term_id ) {

            if ( ! $term_id ) {
                continue;
            }

            if ( ! isset( $args['tax_query'] ) ) {
                $args['tax_query'] = [
                    'relation' => 'AND',
                ];
            }


            $sanitized_taxonomy = 'pa_' . sanitize_text_field( $attr_name );
            $sanitized_term_id = absint( wp_unslash( $term_id ) );

            $args['tax_query'][] = [
                'taxonomy' => $sanitized_taxonomy,
                'field'    => 'term_id',
                'terms'    => [$sanitized_term_id],
            ];

            $args['product_attrs'][$sanitized_taxonomy] = $sanitized_term_id;
        }

        
        $args = apply_filters( 'mdspbe_product_filter_args', $args );
        
        $count = mdspbe_count_products( $args );
        $pages = ceil( $count / $limit );

        // Query the first page if the original page doesn't exist
        if ( $page > $pages ) {
            $args['page'] = 1;
        }

    }
    
    $products = mdspbe_get_products( $args );
    $attributes = mdspbe_get_active_attributes();
    $main_attribute = mdspbe_get_main_attribute_slug();
    require_once MDSPBE_PATH . 'templates/product-list.php';
}

/**
 * Query products
 */
function mdspbe_get_products( $args = [] ) {

    $defaults = [
        'page'      => 1,
        'limit'     => 50,
        'orderby'   => 'id',
        'order'     => 'DESC',
        'return'    => 'objects',
    ];

    // Clean empty values
    $args = array_filter( $args, function ( $value ) {
        return $value !== '';
    });

    // We need to change this array key name for the query
    if ( ! empty( $args['page_number'] ) ) {
        $args['page'] = $args['page_number'];
        unset( $args['page_number'] );
    }

    $query_args = apply_filters( 'mdspbe_product_query_args', array_merge( $defaults, $args ) );

    $products = apply_filters( 'mdspbe_filter_product_query', wc_get_products( $query_args ) );


    // We also try searching by the global unique id and sku
    // It has to be a complete match
    if ( isset( $query_args['s'] ) ) {
        
        // Get product by global unique id
        $product_id = wc_get_product_id_by_global_unique_id( $query_args['s'] );
        if ( $product_id ) {
            $get_product_func = mdspbe_get_product_function_name();
            $product = $get_product_func( $product_id );
            
            if ( $product ) {
                $products[] = $product;
            }
        }

        // Get product by sku
        $product_id = wc_get_product_id_by_sku( $query_args['s'] );
        if ( $product_id ) {
            $get_product_func = mdspbe_get_product_function_name();
            $product = $get_product_func( $product_id );
            
            if ( $product ) {
                $products[] = $product;
            }
        }
        
        if ( class_exists( '\Atum\Suppliers\Suppliers' ) ) {
            $product_id = \Atum\Suppliers\Suppliers::get_product_id_by_supplier_sku( 0, $query_args['s'] );
            if ( $product_id ) {
                $get_product_func = mdspbe_get_product_function_name();
                $product = $get_product_func( $product_id );
                
                if ( $product ) {
                    $products[] = $product;
                }
            }
        }

    }

    // Remove duplicated products
    $unique = [];
    foreach ( $products as $product ) {
        $unique[ $product->get_id() ] = $product;
    }
    $products = array_values( $unique );

    return $products;
}

/**
 * Count products
 */
function mdspbe_count_products( $query_args = [] ) {

    $defaults = [
        'limit'     => -1,
        'orderby'   => 'id',
        'return'    => 'ids',
    ];

    $query_args = array_merge( $query_args, $defaults );

    $count = count( wc_get_products( $query_args ) );

    return $count;
}

/**
 * Get the main attribute slug
 */
function mdspbe_get_main_attribute_slug() {
    return apply_filters( 'mdspbe_main_attribute', 'name' );
}

/**
 * Get the WC visibility options
 */
function mdspbe_get_wc_visibility_options() {
    $options = apply_filters(
        'woocommerce_product_visibility_options', 
        // This is a WooCommerce hook. So I also make it available here, 
        // so if others developers hook into it, their changes also are reflected in this plugin
        array(
            'visible' => esc_html__( 'Visible',  'mds-product-bulk-editor-for-woocommerce' ),
            'catalog' => esc_html__( 'Catalog',  'mds-product-bulk-editor-for-woocommerce' ),
            'search'  => esc_html__( 'Search',  'mds-product-bulk-editor-for-woocommerce' ),
            'hidden'  => esc_html__( 'Hidden',  'mds-product-bulk-editor-for-woocommerce' ),
        )
    );
    return $options;
}

/**
 * Render input
 */
function mdspbe_render_field_content( $product, $attribute, $attributes, $product_type, $i ) {

    if ( ! in_array( $product_type, $attribute['allowed_types'], true ) ) {
        return;
    }

    $type = isset( $attribute['type'] ) ? $attribute['type'] : '';
    $name = $attribute['name'];
    $required = '';
    $required_prototype = '';
    if ( ! empty( $attribute['required'] ) ) {
        if ( $product ) {
            $required = 'required';
        } else {
            $required_prototype = 'js-will-required'; // they will not be required until became in products, no form validation does not interfiere
        }
    }

    $placeholder = esc_html__( 'Double click to go full view mode',  'mds-product-bulk-editor-for-woocommerce' );

    $value = mdspbe_get_value( $product, $attribute );
    if ( is_wp_error( $value ) ) {
        echo '<span class="fs-xs">' . esc_html__( 'Not available in your installation',  'mds-product-bulk-editor-for-woocommerce' ) . '</span>';
        return;
    }

    $style = '';
    if ( ! empty( $attribute['style'] ) ) {
        $all_props = '';
        foreach ( $attribute['style'] as $prop => $val ) {
            $all_props .= $prop . ': ' . $val . '; ';
        }
        $style = 'style="' . $all_props . '"';
    }

    // This is to avoid browser validation on the prototype row
    // And to prevent user editing the field if conditionals are not met
    $disabled = '';
    $conditionals = $attribute['conditionals'] ?? [];
    foreach ( $conditionals as $attr_id => $value_required ) {
        $attr_value = mdspbe_get_value( $product, $attributes[$attr_id] );
        if ( $attr_value !== $value_required ) {
            $disabled = 'disabled';
            break;
        }
    }

    // Useful to disable fields when we are on the trash bin
    $post_status = $_GET['status'] ?? '';
    $disabled = $post_status === 'trash' ? 'disabled' : $disabled;
    
    if ( empty( $attribute['allow_edit'] ) || ( is_array( $attribute['allow_edit'] ) && empty( $attribute['allow_edit'][$product_type] ) ) ) {

        $input = '<span class="fs-xs">' . esc_html( $value ) . '</span>';
        $current_label = '';
    
    } elseif ( $type === 'input_text' ) {
    
        $input = '<input type="text" class="form-control rounded-3 ' . $required_prototype . '" value="' . esc_html( $value ) . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" title="' . $placeholder . '" ' . $style . ' ' . $required . ' ' . $disabled . '>';
        $current_label = $value;
    
    } elseif ( $type === 'input_number' ) {

        $step_attr = ! empty( $attribute['step'] ) ? 'step="' . $attribute['step'] . '"' : '';
        $current_label = $value;
        $input = '<input type="number" class="form-control rounded-3 ' . $required_prototype . '" value="' . esc_html( $value ) . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" ' . $step_attr . ' title="' . $placeholder . '" ' . $style . ' ' . $required . ' ' . $disabled . '>';
        
    } elseif ( $type === 'input_date' ) {

        $current_label = $value;
        $input = '<input type="date" class="form-control rounded-3 ' . $required_prototype . '" value="' . esc_html( $value ) . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" title="' . $placeholder . '" ' . $style . ' ' . $required . ' ' . $disabled . '>';
        
    } elseif ( $type === 'textarea' ) {
    
        $current_label = $value;
        $input = '<textarea class="form-control rounded-3 ' . $required_prototype . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" title="' . $placeholder . '"  ' . $style . ' ' . $required . ' ' . $disabled . '>' . esc_html( $value ) . '</textarea>';

    } elseif ( $type === 'select' ) {
    
        $options_html = '<option value="" hidden disabled></option>';
        if ( is_array( $attribute['options'] ) ) {
            $options = $attribute['options'];
        } else {
            $opts_callback = $attribute['options'];

            if ( isset( $attribute['callbacks_param'] ) ) {
                $options = $opts_callback( $attribute['callbacks_param'] );
            } else {
                $options = $opts_callback();
            }
        }

        // For multiple select we use Tom select
        $is_multiple = ! empty( $attribute['multiple'] );
        if ( $is_multiple ) {
            return;
        }

        // We do this to be make all type of "boolean" fit
        if ( ! empty( $attribute['is_bool'] ) ) {
            $value = mdspbe_format_bool( $value );
        }

        foreach ( $options as $key => $opt ) {
            $options_html .= '<option value="' . esc_html( $key ) . '" ' . selected( $key, $value, false ) . '>' . esc_html( $opt ) . '</option>';
        }

        $input = '<select class="form-select rounded-3 ' . $required_prototype . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" ' . $style . ' ' . $required . ' ' . $disabled . '>' . $options_html . '</select>';
        $current_label = isset( $options[$value] ) ? $options[$value] : '';

    } elseif ( $type === 'input_image' ) {

        $get_image = $attribute['getImage'];
        $get_image_id = $attribute['get'];
        if ( $product && method_exists( $product, $get_image ) && method_exists( $product, $get_image_id ) && $product->$get_image_id() ) {
            $image = $product->$get_image( 'full', array( 'class' => 'rounded-2 js-set-image cursor-pointer', 'style' => 'height:60px; width:auto;' ) );
            $img_actions = '<div class="d-flex flex-column justify-content-center gap-1"><div class="cursor-pointer js-set-image dashicons dashicons-edit"></div> <div class="cursor-pointer js-remove-image dashicons dashicons-trash"></div></div>';
        } else {
            $image = '';
            $img_actions = '<div class="d-flex flex-column justify-content-center"><div class="cursor-pointer js-set-image dashicons dashicons-plus-alt"></div></div>';
        }

        $img_actions = $disabled === 'disabled' ? '' : $img_actions;

        $image_container = '<div class="d-flex align-items-center gap-2 js-image-preview">' . $img_actions . $image . '</div>';

        $current_label = null;
        $input = $image_container . '<input type="number" class="js-input-image ' . $required_prototype . '" value="' . esc_html( $value ) . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" title="' . $placeholder . '" ' . $style . ' ' . $required . ' ' . $disabled . ' hidden>';
        
    } elseif ( $type === 'wp_editor' ) {
    
        $editor_action = $disabled === 'disabled' ? '' : '<div class="cursor-pointer text-center js-wp-edit"><span class="dashicons dashicons-edit"></span></div>';
        $wp_editor_content = '<div class="d-flex flex-row align-items-center justify-content-between gap-2 fs-xs" data-name="' . esc_html( $name ) . '" ' . $style . '>' . $editor_action . ' <div class="flex-grow-1 text-start js-wp-edit-content">' . $value . '</div></div>'; // We don't esc_html this because it may have html in it
        $current_label = null;

        $input = $wp_editor_content . '<textarea class="js-wp-editor ' . $required_prototype . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" title="' . $placeholder . '"  ' . $style . ' ' . $required . ' ' . $disabled . ' hidden>' . esc_html( $value ) . '</textarea>';
    
    } elseif ( $type === 'tom_select' ) { // Only for ajax calls
    
        // Remote data (ajax)
        if ( ! empty( $attribute['ajax_options'] ) ) { 
            // We generate the selected options. We also need to mark them as selected
            $options_html = '';
            $multiple = empty( $attribute['multiple'] ) ? '' : 'multiple';
            
            $selected_opt_name = $attribute['selected_option_name'];
            if ( function_exists( $selected_opt_name ) ) {
                $is_multiple = ! empty( $attribute['multiple'] );
                if ( $is_multiple ) {
                    $current_label = [];
                    foreach ( $value as $val ) {
                        $option_name = $selected_opt_name( $val );
                        $current_label[] = $option_name;
                        $options_html .= '<option value="' . esc_html( $val ) . '" selected>' . esc_html( $option_name ) . '</option>';
                    }
                    $current_label = implode( ', ', $current_label );
                } else {
                    if ( $value ) {
                        $option_name = $selected_opt_name( $value );
                        $current_label = $option_name;
                        $options_html .= '<option value="' . esc_html( $value ) . '" selected>' . esc_html( $option_name ) . '</option>';
                    } else {
                        $current_label = '';
                    }
                }
            } else {
                $current_label = '';
            }

            $remote_data_class = 'js-remote-data';
        } else {

            // only for multiple select
            $is_multiple = ! empty( $attribute['multiple'] );
            if ( ! $is_multiple ) {
                return;
            }

            $multiple = 'multiple';

            // Get the option array
            if ( is_array( $attribute['options'] ) ) {
                $options = $attribute['options'];
            } else {
                $opts_callback = $attribute['options'];
                if ( isset( $attribute['callbacks_param'] ) ) {
                    $options = $opts_callback( $attribute['callbacks_param'] );
                } else {
                    $options = $opts_callback();
                }
            }

            // Generate the option html
            $options_html = '<option value="" hidden disabled></option>';
            foreach ( $options as $key => $opt ) {
                $selected = in_array( $key, $value, true ) ? 'selected' : ''; 
                $options_html .= '<option value="' . esc_html( $key ) . '" ' . $selected . '>' . esc_html( $opt ) . '</option>';
            }
            
            // Get the current label
            $current_label = [];
            foreach ( $value as $val ) {
                if ( isset( $options[$val] ) ) {
                    $current_label[] = $options[$val];
                }
            }
            $current_label = implode( ', ', $current_label ); // Used to show old selected categories

            $remote_data_class = '';
        }
        
        // This is to prepare the encoded array to be output as html
        $value = str_replace( "\"", "'", json_encode( $value ) );
        if ( $value === '[]' ) {
            $value = "['']"; // Needed to compare old and new values in the JS
        }
        
        $tom_select_action = $disabled === 'disabled' ? '' : '<div class="cursor-pointer js-tom-select-edit"><span class="dashicons dashicons-edit"></span></div>';
        $tom_select_content = '<div class="d-flex flex-row align-items-center justify-content-between gap-2 fs-xs" data-name="' . esc_html( $name ) . '" ' . $style . '>' . $tom_select_action . ' <div class="flex-grow-1 text-start js-tom-select-content">' . esc_html( $current_label ) . '</div></div>';
        $input = $tom_select_content . '<select class="js-tom-select ' . $remote_data_class . ' ' . $required_prototype . '" data-value="' . esc_html( $value ) . '" data-name="' . esc_html( $name ) . '" data-id="' . $attribute['id'] . '" ' . $style . ' ' . $required . ' ' . $multiple . ' ' . $disabled . ' hidden>' . $options_html . '</select>';
    
    } else {
        return;
    }

    $margin_start = $i === 0 ? 'ms-4' : '';
    $curr_label_elem = $current_label !== null ? '<div class="fs-xs fst-italic text-muted js-current-label ' . $margin_start . '">' . esc_html__( 'Current:',  'mds-product-bulk-editor-for-woocommerce' ) . ' <span>' . esc_html( $current_label ) . '</span></div>' : '';
    
    $arr = [
        'div' => [
            'class' => true, 
            'style' => true, 
            'data-name' => true
        ], 
        'span' => ['class' => true], 
        'input' => [
            'type' => true, 
            'class' => true, 
            'style' => true, 
            'value' => true, 
            'step' => true,
            'title' => true, 
            'data-value' => true, 
            'data-name' => true, 
            'data-id' => true, 
            'disabled' => true, 
            'hidden' => true, 
            'required' => true
        ], 
        'textarea' => [
            'class' => true, 
            'style' => true, 
            'title' => true, 
            'value' => true, 
            'data-value' => true, 
            'data-name' => true, 
            'data-id' => true,
            'disabled' => true, 
            'hidden' => true, 
            'required' => true
        ], 
        'select' => [
            'class' => true, 
            'style' => true, 
            'title' => true, 
            'value' => true, 
            'data-value' => true, 
            'data-name' => true, 
            'data-id' => true,
            'disabled' => true, 
            'hidden' => true, 
            'required' => true,
            'multiple' => true
        ], 
        'option' => [
            'value' => true,
            'selected' => true,
            'disabled' => true, 
            'hidden' => true, 
        ],
        'img' => [
            'src' => true,
            'class' => true,
            'style' => true
        ]
    ];
    
    
    if ( $i === 0 ) {
        $product_id = $product ? $product->get_id() : 0;
        echo '<div class="d-flex align-items-center gap-2 ms-2">';
        mdspbe_render_product_selector( $product_id );
        echo wp_kses( $input, $arr );
        echo '</div>';
        echo wp_kses( $curr_label_elem, $arr );
        mdspbe_render_product_options( $product_id, $product_type );
    } else {
        echo wp_kses( $input, $arr );
        echo wp_kses( $curr_label_elem, $arr );
    }

}

/**
 * Render a product or product variation
 */
function mdspbe_render_product( $product, $attributes, $product_type = 'simple' ) {
    
    $supported_type = in_array( $product_type, mdspbe_get_supported_product_types(), true );
    if ( ! $product ) {
        $tr_class = 'table-danger';
    } elseif ( ! $supported_type ) {
        $tr_class = 'table-info';
    } elseif ( $product_type === 'variation' ) {
        $tr_class = 'table-warning';
    } else {
        $tr_class = '';
    }
    
    if ( $product ) {
        $product_id = $product->get_id();
        $product_name = $product->get_name();
    } else { // this is when creating an empty row
        $product_id = 0;
        $product_name = '';
    }

    ?>
    <tr data-id="<?php echo esc_attr( $product_id ); ?>" data-product-type="<?php echo esc_attr( $product_type ); ?>" class="hover-parent <?php echo esc_attr( $tr_class ); ?>">
        <?php 
        if ( $supported_type ) {
            $i = 0;
            foreach ( $attributes as $attribute ) { 
                $purchase_order_keep = ! empty( $attribute['purchaseOrderKeep'] ) ? 'js-po-keep' : '';
                $sticky = $i === 0 ? 'sticky-col' : '';
                ?>
                <td data-id="<?php echo esc_attr( $attribute['id'] ) ?>" class="<?php echo esc_attr( $sticky . ' ' . $purchase_order_keep ); ?>">
                    <?php 
                    mdspbe_render_field_content( $product, $attribute, $attributes, $product_type, $i );
                    ?>
                </td>
                <?php 
                $i++;
            }
        } else {
            ?><td colspan="<?php echo count( $attributes ); ?>">
            <?php echo sprintf(
                // translators: %s is the product type that is not supported. IE: composite product
                esc_html__( '%s does not support bulk edition.',  'mds-product-bulk-editor-for-woocommerce' ),
                esc_html( $product_name ),
            ) . ' <a target="_blank" href="' . esc_url( get_edit_post_link( $product_id ) ) . '">' . esc_html__( 'Edit',  'mds-product-bulk-editor-for-woocommerce' ) . '</a>'; ?>
            </td><?php
        } ?>
    </tr>
    <?php
}


/**
 * Render element selector
 */
function mdspbe_render_product_selector( $id ) {
    $class = $id === 'all' ? 'js-select-all' : 'js-element-selector';
    ?>
    <input type="checkbox" value="yes" class="<?php echo esc_attr( $class ); ?>" data-id="<?php echo esc_attr( $id ); ?>" tabindex="-1">
    <?php
}


/**
 * Render element options
 */
function mdspbe_render_product_options( $id, $product_type ) {

    if ( $product_type === 'variation' ) {
        return;
    }

    $style = $id ? '' : 'display: none';

    ?>
    <div class="mt-0 ms-4 hover-child fs-xs">
        <span class="js-row-actions-cont" style="<?php echo esc_attr( $style ); ?>"> 
            <a class="js-row-view-cont" href="<?php echo esc_url( get_permalink( $id ) ); ?>" target="_blank" tabindex="-1"><?php esc_html_e( 'View', 'mds-product-bulk-editor-for-woocommerce' ); ?></a>
            | <a class="js-row-edit-cont" href="<?php echo esc_url( get_edit_post_link( $id ) ); ?>" target="_blank" tabindex="-1"><?php esc_html_e( 'Edit', 'mds-product-bulk-editor-for-woocommerce' ); ?></a>
            <?php if ( $product_type === 'variable' ) { ?>
                | <a class="js-row-create-variation-cont" href="<?php echo esc_url( get_edit_post_link( $id ) ); ?>" target="_blank" tabindex="-1"><?php esc_html_e( 'Add variations',  'mds-product-bulk-editor-for-woocommerce' ); ?></a>
            <?php } ?>
        </span>
        <?php if ( ! $id ) { ?>
        <span class="js-remove-row-cont">
            <a href="#" class="js-remove-row" tabindex="-1"><?php esc_html_e( 'Remove', 'mds-product-bulk-editor-for-woocommerce' ); ?></a>
        </span>
        <?php } ?>
    </div>
    <?php
}


/**
 * Add a simple td element to display the beggining of variations
 */
function mdspbe_render_variation_td( $attributes ) {
    ?>
    <tr class="table-warning">
        <td colspan="<?php echo count( $attributes ); ?>">
            <?php esc_html_e( 'Variations',  'mds-product-bulk-editor-for-woocommerce' ); ?>
        </td>
    </tr>
    <?php
}


/**
 * Render the WP html editor
 */
function mdspbe_render_html_editor() {
    $content = ''; 
    $editor_id = 'mdspbe_wp_editor';
    $settings = [
        'textarea_rows' => 10,
        'editor_class'  => 'js-custom-prompt-wp-editor',
        'media_buttons' => false, 
        'tinymce' => true,
        'quicktags' => true,
    ];

    wp_editor( $content, $editor_id, $settings );
}


/**
 * Get the remove options for tom selects
 */
function mdspbe_get_ajax_options( $term, $attr_id ) {
    $attributes = mdspbe_get_products_attributes();
    $attribute = $attributes[$attr_id];
    $ajax_opts_callback = ! empty( $attribute['ajax_options'] ) ? $attribute['ajax_options'] : '';
    if ( ! function_exists( $ajax_opts_callback ) ) {
        return [];
    }

    return $ajax_opts_callback( $term );
}


/**
 * Search products by name
 */
function mdspbe_search_products_by_name( $term ) {

    $products = wc_get_products( [
        'limit'     => 10,
        's'         => $term,
        'return'    => 'ids'
    ] );

    $results = [];

    foreach ( $products as $product_id ) {
        $product = wc_get_product( $product_id );
        $results[] = [
            'id' => $product_id,
            'name' => $product->get_name(),
        ];
    }

    return $results;
}


/**
 * Get product name by ID
 */
function mdspbe_get_product_name_by_id( $product_id ) {
    $product = wc_get_product( $product_id );
    if ( ! $product ) {
        return '';
    }
    
    $product_name = $product->get_name();
    return $product_name;
}


/**
 * Create or update product properties
 */
function mdspbe_update_create_products( $data ) {
    
    $update = mdspbe_sanitize_fields( $data['update'] );
    $create = mdspbe_sanitize_fields( $data['create'] );

    $attributes = mdspbe_get_products_attributes();

    $response = [
        'update' => [],
        'create' => []
    ];

    // Update products
    if ( current_user_can( 'edit_products' ) ) {
        foreach ( $update as $product_id => $prod_data ) {
            $get_product_func = mdspbe_get_product_function_name();
            $product = $get_product_func( $product_id );
            
            if ( ! $product ) {
                $response['update'][$product_id] = false;
                continue;
            }

            $response['update'][$product_id]['updated'] = mdspbe_update_product( $product, $prod_data, $attributes );
        }
    }

    // Create products
    if ( current_user_can( 'publish_products' ) ) {
        foreach ( $create as $prod_data ) {
            $product_type = $prod_data['prodType'];
            switch ( $product_type ) {
                case 'simple':
                    $product = new WC_Product_Simple();
                    break;
                case 'variable':
                    $product = new WC_Product_Variable();
                    break;
                case 'external':
                    $product = new WC_Product_External();
                    break;
                case 'grouped':
                    $product = new WC_Product_Grouped();
                    break;
                default:
                    $product = apply_filters( 'mdspbe_new_product', null, $prod_data );
                    if ( ! $product instanceof WC_Product ) {
                        continue 2;
                    }
            }
            
            $product->save(); // We save it now to get the product ID
            $product_id = $product->get_id();

            $response['create'][$product_id] = [
                'updated' => mdspbe_update_product( $product, $prod_data, $attributes ),
                'permalink' => esc_url( get_permalink( $product_id ) ),
            ];

        }
    }

    return $response;
}


/**
 * Update product properties
 */
function mdspbe_update_product( $product, $prod_data, $attributes ) {
    $response = [];
    foreach ( $prod_data as $key => $value ) {
        if ( ! isset( $attributes[$key] ) ) {
            $response[$key] = false;
            continue;
        }

        // Accepts empty values?
        // Some methods does not accepts empty values (ie. ATUM supplier ID and supplier SKU)
        if ( ! $value ) {
            if ( isset( $attributes[$key]['accept_empty_value'] ) && $attributes[$key]['accept_empty_value'] === false ) {
                $response[$key] = true;
                continue;
            }
        }

        $attribute = $attributes[$key];

        if ( ! empty( $attribute['is_integer'] ) ) {
            $value = (int) $value;
        }

        if ( ! empty( $attribute['is_meta'] ) ) {
            if ( is_array( $attribute['meta_key'] ) ) {
                // Support for different meta keys by product type
                $product_type = $product->get_type();
                if ( ! empty( $attribute['meta_key'][$product_type] ) ) {
                    $meta_key = $attribute['meta_key'][$product_type];
                    $product->update_meta_data( $meta_key, $value );
                    $response[$key] = true;
                }
            } else {
                $product->update_meta_data( $attribute['meta_key'], $value );
                $response[$key] = true;
            }
            
        } else {
            try {
                $set = $attribute['set'];
                if ( isset( $attribute['are_get_set_functs'] ) && $attribute['are_get_set_functs'] === true && function_exists( $set ) ) {

                    if ( isset( $attribute['callbacks_param'] ) ) {
                        $set( $product, $value, $attribute['callbacks_param'] );
                    } else {
                        $set( $product, $value );
                    }

                    $response[$key] = true;
                } elseif ( method_exists( $product, $set) ) {
                    
                    $product->$set( $value );
                    $response[$key] = true;
            
                } else {
                    $response[$key] = false;
                }
            } catch ( Exception $e ) {
                $response[$key] = false;
            }
        }
        
    }

    $product->save();

    return $response;
}


/**
 * Get active attributes
 */
function mdspbe_get_active_attributes() {
    $attributes = mdspbe_get_products_attributes();
    $active_attribute_keys = mdspbe_get_active_attribute_keys();
    $active_attributes = [];
    foreach ( $attributes as $id => $attribute ) {
        if ( in_array( $id, $active_attribute_keys, true ) ) {
            $active_attributes[$id] = $attribute;
        }
    }

    return $active_attributes;
}


/**
 * Get all attributes statuses
 */
function mdspbe_get_attributes_statuses() {
    $attributes = mdspbe_get_products_attributes();
    $active_attribute_keys = mdspbe_get_active_attribute_keys();
    $attr_statuses = [];
    foreach ( $attributes as $id => $attribute ) {
        $attr_statuses[] = [
            'id' => $id,
            'name' => $attribute['name'],
            'description' => $attribute['description'] ?? '',
            'active' => in_array( $id, $active_attribute_keys, true ),
        ];
    }

    return $attr_statuses;
}


/**
 * Some fields have conditions in order to be active
 * The conditions are defined in wach attribute.
 * We want to transpose this, so the attribute required has an array of all attributes requiring it
 */
function mdspbe_get_attributes_transposed_conditionals() {
    $attributes = mdspbe_get_products_attributes();
    $attr_trans_conditionals = [];
    foreach ( $attributes as $attr_id => $attribute ) {
        if ( ! empty( $attribute['conditionals'] ) && is_array( $attribute['conditionals'] ) ) {
            $conditionals = $attribute['conditionals'];
            foreach ( $conditionals as $cond_attr_key => $cond_attr_value ) {
                if ( ! isset( $attr_trans_conditionals[$cond_attr_key] ) ) {
                    $attr_trans_conditionals[$cond_attr_key] = [];
                }

                $attr_trans_conditionals[$cond_attr_key][] = $attr_id;
            }
        }
    }

    // Make sure this is always formed by simple arrays so it doesn't convert to object when using it in JS
    foreach ( $attr_trans_conditionals as $key => $array ) {
        $attr_trans_conditionals[$key] = array_values( array_unique( $array ) );
    }

    return $attr_trans_conditionals;

}


/**
 * Get all products data for print tags
 */
function mdspbe_get_products_data_for_print_tags( $data ) {
    
    $getters = [];

    if ( isset( $data['show-name'] ) && $data['show-name'] === 'yes' ) {
        $getters['name'] = 'get_name';   
    }
    
    if ( isset( $data['show-sku'] ) && $data['show-sku'] === 'yes' ) {
        $getters['sku'] = 'get_sku';   
    }
    
    if ( isset( $data['show-categories'] ) && $data['show-categories'] === 'yes' ) {
        $getters['category_ids'] = 'get_category_ids';   
    }
    
    if ( isset( $data['show-price'] ) && $data['show-price'] === 'yes' ) {
        $getters['price'] = 'get_price_html'; 
    }
    
    if ( isset( $data['show-global-id'] ) && $data['show-global-id'] === 'yes' ) {
        $getters['global_unique_id'] = 'get_global_unique_id';   
    }

    $products_ids = ! empty( $data['prodsIds'] ) ? $data['prodsIds'] : [];
    $products_data = [];
    foreach ( $products_ids as $product_id ) {

        $get_product_func = mdspbe_get_product_function_name();
        $product = $get_product_func( $product_id );

        if ( ! $product ) {
            continue;
        }

        $products_data[$product_id] = [];

        foreach ( $getters as $key => $getter ) {
            if ( method_exists( $product, $getter ) ) {
                $products_data[$product_id][$key] = $product->$getter();
            }
        }

    }

    return $products_data;
}


/**
 * Function to retrieve the get_product function name
 */
function mdspbe_get_product_function_name() {
    return apply_filters( 'mdspbe_get_product_function_name', 'wc_get_product' );
}