<?php

namespace Miladmodaresi\Taamito\Services;

use WC_Product;
use WC_Product_Attribute;
use WC_Product_Variable;
use WC_Product_Variation;
use WP_Query;

/**
 * @property WC_Product $productModel
 */
class ProductService
{

    protected $productModel = null;
    protected $priceLocalMap = [];

    public function create($input, $hasVariables = false)
    {
        $this->priceLocalMap = [];
        if ($hasVariables) {
            $this->productModel = new WC_Product_Variable();
        } else
            $this->productModel = new WC_Product();

        $product = $this->getFields($input, 'create');
        $this->productModel->set_props($product);
        $this->productModel->save();

        if (!$hasVariables) {
            $this->applySimplePriceData($input['prices'] ?? []);
        }

        if (!$hasVariables && isset($input['prices'][0]['id'])) {
            $this->priceLocalMap[$input['prices'][0]['id']] = $this->productModel->get_id();
        }

        return $this;
    }

    public function update($id, $input, $hasVariables = false)
    {
        $this->priceLocalMap = [];
        if ($hasVariables) {
            $this->productModel = new WC_Product_Variable($id);
        } else
            $this->productModel = new WC_Product($id);


        $product = $this->getFields($input, 'update');

        $this->productModel->set_props($product);
        $this->productModel->save();

        if (!$hasVariables) {
            $this->applySimplePriceData($input['prices'] ?? []);
        }

        if (!$hasVariables && isset($input['prices'][0]['id'])) {
            $this->priceLocalMap[$input['prices'][0]['id']] = $this->productModel->get_id();
        }

        return $this;
    }

    private function getFields($input, $type = 'create'): array
    {
        $fields = taamitoEnsureFieldsOption();
        $result = [];
        foreach ($input as $key => $item) {
            if ($fields[$key] == 0)
                continue;

            if (isset($fields[$key]) && $fields[$key] == 1 && $type == 'create')
                $result[$key] = $item;
            elseif (isset($fields[$key]))
                $result[$key] = $item;
        }

        return $result;
    }

    public function delete($id)
    {
        if (taamitoApp()->getOption('can_delete'))
        return $this;

        $this->productModel = new WC_Product($id);

        $this->productModel->delete();
        return $this;
    }
    public function find($id)
    {
        $this->productModel = new WC_Product($id);
        return $this;
    }

    public function setTags($input)
    {
        $tags = [];
        foreach ($input as $tag) {
            if (($term = term_exists($tag, 'product_tag')))
                $tags[] = $term['term_id'];
            else
                $tags[] = wp_insert_term($tag, 'product_tag')['term_id'];
        }
        $this->productModel->set_tag_ids($tags);
        $this->productModel->save();
        return $this;
    }

    public function createProductVariation($productId, $variationData)
    {
        // Get the Variable product object (parent)
        $product = wc_get_product($productId);

        $variationPost = array(
            'post_title'  => $product->get_name(),
            'post_name'   => 'product-' . $productId . '-variation',
            'post_status' => 'publish',
            'post_parent' => $productId,
            'post_type'   => 'product_variation',
            'guid'        => $product->get_permalink()
        );


        $variation = new WP_Query([
            'name'           => 'product-' . $productId . '-variation',
            'post_type'      => 'product_variation',
            'post_status'    => 'publish',
            'posts_per_page' => 1
        ]);
        $variation = $variation->have_posts() ? $variation->get_post() : false;

        $variationId = null;

        if (!$variation)
            $variationId = wp_insert_post($variationPost);
        else
            $variationId = $variation->ID;

        // Get an instance of the WC_Product_Variation object
        $variation = new WC_Product_Variation($variationId);

        // Iterating through the variations attributes
        foreach ($variationData['combinations'] as $combination) {

            $taxonomy = wc_attribute_taxonomy_name($combination['feature']); // The attribute taxonomy
            // If taxonomy doesn't exists we create it (Thanks to Carl F. Corneil)
            if (!taxonomy_exists($taxonomy)) {
                register_taxonomy(
                    $taxonomy,
                    'product_variation',
                    array(
                        'hierarchical' => false,
                        'label' =>  $combination['feature'],
                        'query_var' => true,
                        'rewrite' => array('slug' => sanitize_title($combination['feature'])), // The base slug
                    ),
                );
            }

            // Check if the Term name exist and if not we create it.
            if (!term_exists($combination['feature_value'], $taxonomy))
                wp_insert_term($combination['feature_value'], $taxonomy); // Create the term

            $termSlug = get_term_by('name', $combination['feature_value'], $taxonomy)->slug; // Get the term slug

            // $termSlug = urldecode($termSlug);
            // Get the post Terms names from the parent variable product.
            $postTermNames =  wp_get_post_terms($productId, $taxonomy, array('fields' => 'names'));
            // Check if the post term exist and if not we set it in the parent variable product.

            if (!in_array($combination['feature_value'], $postTermNames))
                wp_set_post_terms($productId, $combination['feature_value'], $taxonomy, true);
            // Set/save the attribute data in the product variation
            if (!str_contains($termSlug, 'pa_'))
                $termSlug = 'pa_' . $termSlug;

            update_post_meta($variationId, 'attribute_' . utf8_uri_encode($taxonomy), $termSlug);
        }

        ## Set/save all other data

        // SKU
        // if( ! empty( $variationData['code'] ) )
        //     $variation->set_sku( $variationData['code'] );

        // Prices

        $variation->set_price($variationData['price']);
        $variation->set_regular_price($variationData['price']);
        // $variation->set_sale_price($variationData['price']);
        // $variation->set_sale_price($variationData['price']);

        // $variation->set_regular_price( $variationData['regular_price'] );

        // Stock
        if (!empty($variationData['stock'])) {
            $variation->set_stock_quantity($variationData['stock']);
            $variation->set_manage_stock(true);
            $variation->set_stock_status('');
        } else {
            $variation->set_manage_stock(false);
        }
        if ($variationData['continue_sell'])
            $variation->set_backorders('yes');

        $variation->set_weight($this->productModel->get_weight()); // weight (reseting)
        $variation->set_height($this->productModel->get_height()); // height (reseting)
        $variation->set_width($this->productModel->get_width()); // width (reseting)
        $variation->set_length($this->productModel->get_length()); // width (reseting)
        try {
            if (isset($variationData['code']))
                $variation->set_sku($variationData['code']); // sku (reseting)
        } catch (\Throwable $th) {
            //throw $th;
        }

        $variation->save(); // Save the data
        return $variation;
    }

    public function setAttributes($input)
    {
        $features = [];

        foreach ($input['prices'] as $key => $price) {
            // $variation = new WC_Product_Variation();
            // $children = [];
            // $combinations = [];

            foreach ($price['combinations'] as $item) {
                $taxonomy = wc_attribute_taxonomy_id_by_name($item['feature']);

                if ($taxonomy)
                    $combinations[$key] = $taxonomy;
                else
                    $combinations[$key] = wc_create_attribute(['name' => $item['feature']]);

                $combinations[$key] = wc_get_attribute($combinations[$key]);
                $taxonomy = wc_attribute_taxonomy_name($item['feature_value']); // The attribute taxonomy

                if (!taxonomy_exists($combinations[$key]->slug))
                    register_taxonomy($combinations[$key]->slug, array('product'), array());
                $term = null;

                if (!term_exists($item['feature_value'], $combinations[$key]->slug)) {
                    $term = wp_insert_term($item['feature_value'],  $combinations[$key]->slug, ['slug' => $taxonomy, 'post_type' => 'product', 'taxonomy' => $combinations[$key]->slug]);
                }
                $term = get_term_by('name', $item['feature_value'], $combinations[$key]->slug)->name;
                $features[$combinations[$key]->slug][] = $term;
                // $taxonomy = wc_attribute_taxonomy_id_by_name($item['feature']);
                // if ($taxonomy)
                //     $combinations[$key] = $taxonomy;
                // else
                //     $combinations[$key] = wc_create_attribute(['name' => $item['feature']]);



                // if (!taxonomy_exists($combinations[$key]->slug))
                //     register_taxonomy($combinations[$key]->slug, array('product'), array());
                // if (!term_exists($item['feature_value'], $combinations[$key]->slug))
                //     $term = wp_insert_term($item['feature_value'],  $combinations[$key]->slug, ['post_type' => 'product', 'taxonomy' => $combinations[$key]->slug]);
                // else
                //     $term = get_term_by('name', $item['feature_value'], $combinations[$key]->slug)->slug;


                // $children[] = $term;
            }

            // $variation->set_parent_id($this->productModel->get_id());
            // $variation->set_price($price['purchase_price']);
            // $variation->set_sale_price($price['price']);
            // $variation->set_attributes($children);
            // $variation->save();
            // $variations[] = $variation;
        }
        foreach ($features as $key => $featureValue) {
            $taxonomy = wc_attribute_taxonomy_id_by_name($key);

            $attributeModel = new WC_Product_Attribute();
            $attributeModel->set_id($taxonomy);
            $attributeModel->set_name($key);
            $attributeModel->set_options($featureValue);
            $attributeModel->set_visible(1);
            $attributeModel->set_variation(1);
            $attributeModel->set_position(0);

            $children[] = $attributeModel;
        }

        $this->productModel->set_attributes($children);
        $this->productModel->save();

        foreach ($input['prices'] as $price) {
            $variation = $this->createProductVariation($this->productModel->get_id(), $price);
            if ($variation && isset($price['id'])) {
                $this->priceLocalMap[$price['id']] = $variation->get_id();
            }
        }

        $this->productModel->save();

        return $this;
    }
    /**
     * @deprecated
     */
    public function setImages($input, $files)
    {
        $oldImages = $this->productModel->get_gallery_image_ids();
        $oldThumbnail = $this->productModel->get_image_id();
        if (is_array($oldImages) && count($oldImages)) {
            taamitoApp()->deleteImages($oldImages);
            $this->productModel->set_gallery_image_ids([]);
        }
        if ($oldThumbnail) {
            taamitoApp()->deleteImage($oldThumbnail);
            $this->productModel->set_image_id('');
        }

        $files = taamitoApp()->normalize_files($_FILES);
        if (isset($files['thumbnail'])) {
            $thumbnailId = taamitoApp()->uploadImage($files['thumbnail'], [
                "name"              => $input['name'],
                "short_description" => $input['short_description'],
            ]);
            $this->productModel->set_image_id($thumbnailId);
        }

        $images = [];
        if (isset($files['images']) && $files['images'])
            foreach ($files['images'] as $image) {

                $images[] = taamitoApp()->uploadImage($image, [
                    "name"              => $input['name'],
                    "short_description" => $input['short_description'],
                ]);
            }
        $this->productModel->set_gallery_image_ids($images);
        $this->productModel->save();
        return $this;
    }

    public function setImagesRemote($input)
    {
        $oldImages = $this->productModel->get_gallery_image_ids();
        $oldThumbnail = $this->productModel->get_image_id();
        if (is_array($oldImages) && count($oldImages)) {
            taamitoApp()->deleteImages($oldImages);
            $this->productModel->set_gallery_image_ids([]);
        }
        if ($oldThumbnail) {
            taamitoApp()->deleteImage($oldThumbnail);
            $this->productModel->set_image_id('');
        }
        if (isset($input['thumbnail']) && $input['thumbnail']) {
            $thumbnailId = taamitoApp()->uploadImage($input['thumbnail'], [
                "name"              => $input['name'],
                "short_description" => $input['short_description'],
            ]);
            $this->productModel->set_image_id($thumbnailId);
        }

        $images = [];
        if (isset($files['images']) && $files['images'])
            foreach ($files['images'] as $image) {

                $images[] = taamitoApp()->uploadImage(file_get_contents($image), [
                    "name"              => $input['name'],
                    "short_description" => $input['short_description'],
                ]);
            }
        $this->productModel->set_gallery_image_ids($images);
        $this->productModel->save();
        return $this;
    }

    public function get()
    {
        return $this->productModel->get_data();
    }

    public function getPriceLocalMap(): array
    {
        return $this->priceLocalMap;
    }

    private function applySimplePriceData(array $prices): void
    {
        if (empty($prices) || !is_array($prices[0])) {
            return;
        }

        $price = $prices[0];

        if (isset($price['price'])) {
            $this->productModel->set_regular_price($price['price']);
            $this->productModel->set_price($price['price']);
        }

        if (isset($price['sale_price'])) {
            $this->productModel->set_sale_price($price['sale_price']);
        }

        if (array_key_exists('stock', $price)) {
            $this->productModel->set_manage_stock(true);
            $this->productModel->set_stock_quantity($price['stock']);

            if (!empty($price['continue_sell'])) {
                $this->productModel->set_backorders('yes');
                $this->productModel->set_stock_status('onbackorder');
            } else {
                $status = $price['stock'] > 0 ? 'instock' : 'outofstock';
                $this->productModel->set_stock_status($status);
            }
        } else {
            $this->productModel->set_manage_stock(false);
        }

        $this->productModel->save();
    }
}
