<?php

/**
 * Oct8ne
 *
 * @author      Oct8ne
 * @version     1.0.0
 */
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}
//file_find_require('wp-load.php');
require_once(plugin_dir_path(__FILE__) . '../../helpers/responsehelper.php');
include_once(plugin_dir_path(__FILE__) . '../../helpers/loginhelper.php');
require_once(plugin_dir_path(__FILE__) . '../../helpers/loghelper.php');
//require_once(my_plugin_get_admin_path() . 'includes/plugin.php');

//wp();

//postProcess();

function postProcess() {

    $meth = filter_input(INPUT_GET, 'octmethod');

    $connector = new Oct8neConnector();

    try {
        $meth .= 'OcthMethod';
        if (isset($meth) && method_exists($connector, $meth)) {

            $data = $connector->$meth();

            Oct8neResponseHelper::buildResponse($data);
        } else {

            throw new Exception("Method not Exists");
        }
    } catch (Exception $ex) {

        Oct8neLogHelper::LogException($ex);
    }

    die();
}

/**
 * Logica y metodos de oct8ne
 * Class Oct8neConnector
 */
class Oct8neConnector {

    private $version = "1.2.6";

    /**
     * Obtiene datos de un producto
     * @param $id_product
     * @param bool $extended
     * @return array
     */
    public function getProductData($id_product, $locale, $extended = false) {

        $result = array();

        $includes_param = filter_input(INPUT_GET, 'includes');
        $includes = array();
        if (!empty($includes_param)) {
            $includes = array_map('trim', explode(',', $includes_param));
        }

        $translation_engine_name = get_option('oct8ne_translation_engine', 'any');

        if ($translation_engine_name == "any") {

            $product = wc_get_product($id_product);
        } else {

            $engine = Oct8neTranslationFactory::create("$translation_engine_name");

            if (isset($locale) && !empty($locale)) {
                $locale_ex = explode("-", $locale);
                $locale = $locale_ex[0];
            } else {

                $locale = $engine->getLocale();
            }

            $product = $engine->getProduct($id_product, $locale);
        }


        if (!isset($product) || $product == false)
            return null;

        $type = $product->get_type();
        global $woocommerce;

        $decimalCount = 2;
        $symbol = get_woocommerce_currency_symbol();
        if (!isset($symbol)) {
            $symbol = "";
        }

        $symbol = html_entity_decode($symbol);

        $price = "";
        $regular_price = "";

        if ($type == "variable") {
            $variations = $product->get_variation_prices(true)["price"];
            reset($variations);
            $key = key($variations);
            if($key != null){
                $price = $variations[$key];
            }

            $variations = $product->get_variation_prices(true)["regular_price"];
            reset($variations);
            $key = key($variations);
            if($key != null){
                $regular_price = $variations[$key];
            }
        }

        $priceWithTax = wc_get_price_including_tax($product, array('price' => $product->get_price()));
        $prevPriceWithTax = wc_get_price_including_tax($product, array('price' => $product->get_regular_price()));

        $result["internalId"] = $id_product;
        $result["title"] = $product->get_name();
        $result["formattedPrice"] = $type == "variable" ? $price . " " . $symbol : (is_null($priceWithTax) || empty($priceWithTax) ? "" : number_format_i18n($priceWithTax, $decimalCount) . " {$symbol}");
        $result["formattedPrevPrice"] = $type == "variable" ? $regular_price . " " . $symbol : (is_null($prevPriceWithTax) || empty($prevPriceWithTax) ? "" : number_format_i18n($prevPriceWithTax, $decimalCount) . " {$symbol}");
        $result["productUrl"] = $this->cleanProtocol(get_permalink($id_product));

        //si el producto tiene thumnail
        if (has_post_thumbnail($id_product)) {
            $attachment_ids[0] = get_post_thumbnail_id($id_product);
            $attachment = wp_get_attachment_image_src($attachment_ids[0], 'full');
            $result["thumbnail"] = $this->cleanProtocol($attachment[0]);
        } else {

            $result["thumbnail"] = "";
        }

        //ProductInfo
        if ($extended) {

            $result["description"] = $product->get_description();
            $result["addToCartUrl"] = $type == "variable" ? $this->cleanProtocol($product->add_to_cart_url()) : $this->cleanProtocol(get_home_url()) . "?add-to-cart={$id_product}";
            $result["useProductUrl"] = $type == "variable" ? "true" : "false";

            $medias_aux = $product->get_gallery_image_ids();
            $medias = array();

            if (!empty($result["thumbnail"])) {
                $medias[] = array("url" => $result["thumbnail"]);
            }

            foreach ($medias_aux as $media) {
                $url = wp_get_attachment_image_src($media, 'full')[0];
                $urlmedia = $this->cleanProtocol($url);

                if ($urlmedia != $result["thumbnail"]) {
                    $medias[] = array("url" => $urlmedia);
                }
            }
            $result["medias"] = $medias;
        }

        if (in_array('stock', $includes)) {
            $stock_quantity = $product->get_stock_quantity();
            $final_quantity = ( is_null($stock_quantity) && $product->is_in_stock() ) ? 9999 : (int)$stock_quantity;
            $availability = $product->get_availability();
            $label_stock = !empty($availability['availability']) ? $availability['availability'] : ($product->is_in_stock() ? 'En stock' : 'Agotado');
            $minimal_quantity = apply_filters( 'woocommerce_quantity_input_min', 1, $product );
            if ( !is_numeric($minimal_quantity) || $minimal_quantity < 1 ) {
                $minimal_quantity = 1;
            }

            $result["stock"] = array(
                "quantity"         => $final_quantity,
                "minimal_quantity" => (int)$minimal_quantity, 
                "allowOutStock"    => $product->backorders_allowed(), 
                "labelStock"       => html_entity_decode(strip_tags($label_stock))
            );
        }

        return $result;
    }

    /**
     * Contiene informacion sobre el producto
     * @return array
     */
    public function productInfoOcthMethod() {

        return $this->chooseProductSummaryInfo(true);
    }

    /**
     * Obtiene informacion simple sobre el producto. LLama a getSummary
     * @return array
     */
    public function productSummaryOcthMethod() {
        return $this->chooseProductSummaryInfo(false);
    }

    /**
     * Obtiene la informacion básica (ProductSummary) o extendida (ProductInfo)
     * @param bool $extended
     * @return array
     */
    private function chooseProductSummaryInfo($extended = false) {

        $result = array();

        $ids = filter_input(INPUT_GET, 'productIds');

        $locale = filter_input(INPUT_GET, 'locale');

        if (isset($ids) && !empty($ids)) {

            $ids = explode(",", $ids);

            foreach ($ids as $id) {

                if (is_numeric($id)) {

                    $product = $this->getProductData($id, $locale, $extended);
                    if (isset($product)) {
                        $result[] = $product;
                    }
                }
            }
        }

        return $result;
    }

    /**
     * Devuelve la busqueda de productos por los paremetros de entrada especificados
     * @return array
     */
    //https://codex.wordpress.org/Class_Reference/WP_Query#Status_Parameters
    //https://wordpress.stackexchange.com/questions/139196/display-all-products-by-category-with-woocommerce
    public function searchOcthMethod() {

        $searchengine = Oct8neSearchFactory::create(get_option('oct8ne_search_engine', 'woocommerce'));

        $result = $searchengine->search();

        return $result;
    }

    public function getOrderDetailsOcthMethod() {
        $reference = isset($_GET["reference"]) ? sanitize_text_field($_GET["reference"]) : '';
        $apiToken = isset($_GET["apiToken"]) ? sanitize_text_field($_GET["apiToken"]) : '';
        $localApiToken = get_option('oct8ne_token');

        if ($apiToken != $localApiToken)
            return;

        $order_id = 0;
        $args = array(
            'post_type' => 'shop_order',
            'post_status' => 'any',
            'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                'relation' => 'OR',
                array(
                    'key' => '_ywson_custom_number_order_complete',
                    'value' => $reference, //here you pass the Order Number
                    'compare' => '=',
                ),
                array(
                    'key' => 'ywson_custom_quote_number_order',
                    'value' => $reference, //here you pass the Order Number
                    'compare' => '=',
                ),
                array(
                    'key' => 'ywson_custom_subscription_number_order',
                    'value' => $reference, //here you pass the Order Number
                    'compare' => '=',
                ),
                array(
                    'key' => '_order_number',
                    'value' => $reference, //here you pass the Order Number
                    'compare' => '=',
                )
            )
        );
        $query = new WP_Query($args);

        if (!empty($query->posts)) {
            $order_id = $query->posts[0]->ID;
        }
        if ($order_id == 0)
            $order_id = $reference;

        $order = array();
        $orderWc = wc_get_order($order_id);

        if ($orderWc == null)
            return $order;

        $orderDetails = $orderWc->get_data();
        $trackingNumber = "";
        $trackingURL = "";
        $carrier = "";

        if (is_plugin_active("coordinadora/index.php")) {
            $trackingNumber = get_post_meta($order_id, '_coordinadora_tracking_number', true);
            $trackingURL = get_post_meta($order_id, '_coordinadora_tracking_url', true);

            if (!empty($trackingURL)) {
                $carrier = "Coordinadora";
            }
        }

        $order["date"] = $orderWc->get_date_created()->date("Y-m-d H:i:s");
        $order["reference"] = $orderWc->get_order_number();
        $order["total"] = $orderDetails["total"];
        $order["currency"] = $orderDetails["currency"];
        $order["labelState"] = $orderDetails["status"];
        $order["deliveryDate"] = "";
        $order["carrier"] = $carrier;
        $order["trackingNumber"] = $trackingNumber;
        $order["trackingUrl"] = $trackingURL;
        $order["products"] = [];
        $order["comments"] = [];

        $items = $orderWc->get_items();
        foreach ($items as $item) {
            $product = array();
            $product["name"] = $item->get_name();
            $product["quantity"] = $item->get_quantity();
            array_push($order["products"], $product);
        }
        try {
            $order_notes = wc_get_order_notes(
                    array(
                        'order_id' => $order_id,
                        'type' => 'customer',
                    )
            );

            foreach ($order_notes as $order_note) {
                $note = array();
                $note["message"] = $order_note->content;
                $note["customer"] = true;
                array_push($order["comments"], $note);
            }
        } catch (Exception $ex) {
            
        }

        return $order;
    }

    public function getOrdersOcthMethod() {
        $apiToken = isset($_GET["apiToken"]) ? sanitize_text_field($_GET["apiToken"]) : '';
        $email = isset($_GET["customerEmail"]) ? sanitize_email($_GET["customerEmail"]) : '';

        $localApiToken = get_option('oct8ne_token');

        if ($apiToken != $localApiToken)
            return;

        $orderList = [];
        $orderArg = array('customer' => $email, 'limit' => -1);
        $orders = wc_get_orders($orderArg);
        if ($orders) {
            foreach ($orders as $orderWc) {
                $orderDetails = $orderWc->get_data();

                $order = array();
                $order["date"] = $orderWc->get_date_created()->date("Y-m-d H:i:s");
                $order["reference"] = $orderWc->get_order_number();
                $order["total"] = $orderDetails["total"];
                $order["currency"] = $orderDetails["currency"];
                $order["labelState"] = $orderDetails["status"];
                $order["deliveryDate"] = "";
                if ($order["reference"])
                    array_push($orderList, $order);
            }
        }

        return $orderList;
    }

    /**
     * Obtiene informacion de productos relacionados con el indicado
     * @return array
     */
    public function productRelatedOcthMethod() {

        $result = array();

        $id = filter_input(INPUT_GET, 'productId');
        $locale = filter_input(INPUT_GET, 'locale');

        if (isset($id) && !empty($id)) {

            if (is_numeric($id)) {

                $product = new WC_Product($id);
                $categories = $product->get_category_ids();

                $args = array();
                $args["posts_per_page"] = 11;
                $args["post_type"] = "product";
                $args["post_status"] = "publish";

                $args["tax_query"] = array(array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
                        'taxonomy' => 'product_cat', //the slug of the taxonomy you want to get
                        'field' => 'term_id',
                        'terms' => $categories,
                        'operator' => 'IN'
                ));

                //para obtener el total
                $my_query = new WP_Query($args);
                $count = $my_query->found_posts;

                $result["total"] = $count;

                $myposts = get_posts($args);

                foreach ($myposts as $post) {

                    if ($post->ID != $id)
                        $product = $this->getProductData($post->ID, $locale);

                    if (isset($product)) {
                        $result["results"][] = $product;
                    }
                }
            }
        }

        return $result;
    }

    /**
     * @return array
     * Obtiene informacion sobre el usuario
     */
    public function customerDataOcthMethod() {
        $result = array();
        $wishlist = array();
        $cart = array();

        $locale = filter_input(INPUT_GET, 'locale');

        $id = get_current_user_id();

        if (isset($id) && !empty($id)) {

            $user = new WC_Customer($id);

            $result["id"] = $id;
            $result["firstName"] = $user->get_first_name();
            $result["lastName"] = $user->get_last_name();
            $result["email"] = $user->get_email();
        }


        global $woocommerce;
        if (null === WC()->cart) {
            wc_load_cart(); // Inicializa el carrito de WooCommerce si aún no lo está
        }

        // Obtén el carrito de compras actual
        $cart_aux = WC()->cart->get_cart();

        if (isset($cart_aux)) {

            $cart_aux = $woocommerce->cart->get_cart();
            foreach ($cart_aux as $line) {

                $summary = $this->getProductData($line["product_id"], $locale);

                if (isset($summary)) {
                    $summary["qty"] = $line["quantity"];
                    $cart[] = $summary;
                }
            }
        }

        $wishlist_items = $this->getWishListOcthMethod();

        foreach ($wishlist_items as $item) {

            $product = $this->getProductData($item, $locale);

            if (isset($product)) {
                $wishlist[] = $product;
            }
        }
        $result["wishlist"] = $wishlist;
        $result["cart"] = $cart;

        return $result;
    }

    /**
     * Añadir productos a la lista blanca
     * @return bool
     * @throws PrestaShopException
     */
    public function addToWishListOcthMethod() {

        $engine = WishListFactory::create(get_option("oct8ne_wishlist_engine"));

        if (isset($engine)) {

            return $engine->addToWishList();
        }

        return false;
    }

    /**
     * Obtiene la lista de desos
     * @return bool
     */
    private function getWishListOcthMethod() {

        $engine = WishListFactory::create(get_option("oct8ne_wishlist_engine"));

        if (isset($engine)) {

            return $engine->getWishList();
        }

        return array();
    }

    /**
     * Obtiene el carro de compra
     * @return array
     */
    public function getCartOcthMethod() {
        $result = array();
        $result["price"] = "0";
        $result["finalPrice"] = "0";
        $result["currency"] = "";
        $result["totalItems"] = "0";
        $result["cart"] = array();
        
        return $result;
    }

    /**
     * Obtiene un informe de los productos vendidos a traves de oct8ne entre dos fechas
     * @return array
     */
    public function getSalesReportOcthMethod() {
        $result = array();        

        return $result;
    }

    /**
     * Devuelve informacion sobre el modulo
     * @return array
     */
    public function getAdapterInfoOcthMethod() {

        $result = array();

        $result["platform"] = "Woocommerce";
        $result["adapterName"] = "Oct8ne official adapter for Woocommerce";
        $result["adapterVersion"] = $this->version;
        $result["developedBy"] = "Oct8ne Inc";
        $result["supportUrl"] = "";
        $result["apiVersion"] = "2.3";
        $result["enabled"] = (is_plugin_active("oct8ne/oct8ne.php")) ? 1 : 0;
        $result['searchEngine'] = get_option('oct8ne_search_engine', 'woocommerce');

        return $result;
    }

    /**
     * Quita el protocolo
     * @param $string
     * @return mixed
     */
    private function cleanProtocol($string) {

        $aux = str_replace("https:", "", $string);
        $aux = str_replace("http:", "", $aux);
        return $aux;
    }

    static function alter_posts_where_clause($where) {
        global $wpdb;

        // 1. Obtenemos el valor crudo.
        // Se corrigió '$search1' por 'search1'.
        $raw_search = filter_input(INPUT_GET, 'search1');

        // 2. Comprobamos si el parámetro existe (si no, $raw_search es null).
        // Esto evita el error "trim(): Passing null".
        if (is_null($raw_search)) {
            return $where;
        }

        // 3. Ahora que sabemos que no es null, aplicamos trim()
        $trimmed_search = trim($raw_search);

        // 4. Saneamos el string usando el filtro moderno recomendado.
        // Reemplazamos FILTER_SANITIZE_STRING por FILTER_SANITIZE_FULL_SPECIAL_CHARS.
        $search = filter_var($trimmed_search, FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_NULL_ON_FAILURE);

        // 5. Comprobamos si el resultado es nulo o está vacío después de limpiar.
        if (empty($search)) {
            return $where;
        }

        // 6. El resto de tu código para preparar la consulta SQL está bien.
        $search = $wpdb->esc_like($search);
        $where .= $wpdb->prepare(" AND {$wpdb->posts}.post_title LIKE '%s'", "%{$search}%");

        return $where;
    }
}

function file_find_require($file, $folder = null) {
    if ($folder === null) {
        $folder = dirname(__FILE__);
    }
    $path = $folder . DIRECTORY_SEPARATOR . $file;
    if (file_exists($path)) {
        require($path);
        return $folder;
    } else {
        $upfolder = file_find_require($file, dirname($folder));
        if ($upfolder != '') {
            return $upfolder;
        }
    }
}

function my_plugin_get_admin_path() {
    $admin_path = str_replace(get_bloginfo('url') . '/', ABSPATH, get_admin_url());

    $admin_path = apply_filters('my_plugin_get_admin_path', $admin_path);
    return $admin_path;
}
