<?php

namespace iwbvel\classes\services\product_update\variation_handlers;

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

use iwbvel\classes\repositories\Product;
use iwbvel\classes\services\background_process\VariationBackgroundProcess;
use iwbvel\classes\services\product_update\Variation_Update_Handler;

class Delete_Variation_Handler extends Variation_Update_Handler
{
    private $product_ids;
    private $update_data;
    private $is_processing;
    private $max_process_count;

    public function __construct()
    {
        $this->max_process_count = 100;
    }

    public function is_processing()
    {
        return $this->is_processing;
    }

    public function update($product_ids, $update_data)
    {
        $this->product_ids = $product_ids;
        $this->update_data = $update_data;

        switch ($update_data['action']) {
            case 'delete_by_term':
                $this->delete_by_term();
                break;
            case 'delete_by_ids':
                $this->delete_by_ids();
                break;
            case 'delete_all':
                $this->delete_all();
                break;
        }
    }

    private function delete_by_term()
    {
        if (count($this->product_ids) > 5 && VariationBackgroundProcess::is_enable()) {
            $background_process = VariationBackgroundProcess::get_instance();
            $this->is_processing = true;
            foreach ($this->product_ids as $variable_id) {
                $background_process->push_to_queue([
                    'handler' => 'variation_delete',
                    'delete_class' => self::class,
                    'variable_id' => intval($variable_id),
                    'delete_data' => $this->update_data
                ]);
                $background_process->save();
            }
            if (empty($this->update_data['background_process'])) {
                $background_process->set_total_tasks(count($this->product_ids));
            }
            $background_process->start();
        } else {
            $this->do_delete_by_term();
        }

        return true;
    }

    private function do_delete_by_term()
    {
        foreach ($this->product_ids as $product_id) {
            $product = wc_get_product(intval($product_id));
            if (!($product instanceof \WC_Product_Variable)) {
                continue;
            }

            $product_variations = $product->get_children();
            if (empty($product_variations)) {
                continue;
            }

            $this->attribute_update([
                'product' => $product,
                'attribute' => $this->update_data['value']['attribute'],
                'term' => $this->update_data['value']['term']
            ]);

            $deleted_ids = [];
            foreach ($product_variations as $key => $variation_id) {
                $variation = wc_get_product(intval($variation_id));
                if ($variation instanceof \WC_Product_Variation) {
                    $variation_attributes = $variation->get_attributes();

                    if (
                        !empty($variation_attributes)
                        && is_array($variation_attributes)
                        && isset($variation_attributes[sanitize_text_field($this->update_data['value']['attribute'])])
                    ) {
                        if ($variation_attributes[sanitize_text_field($this->update_data['value']['attribute'])] == sanitize_text_field($this->update_data['value']['term'])) {
                            $deleted_ids[] = $variation_id;
                            continue;
                        }

                        if ($this->update_data['value']['term'] == 'all_terms') {
                            if (count($variation_attributes) === 1) {
                                $deleted_ids[] = $variation_id;
                            }

                            if (count($variation_attributes) > 1) {
                                unset($variation_attributes[sanitize_text_field($this->update_data['value']['attribute'])]);
                                $variation->set_attributes($variation_attributes);
                                $variation->save();
                            }
                        }
                    }
                }
            }

            if (!empty($deleted_ids)) {
                foreach ($deleted_ids as $variation_id) {
                    wp_delete_post(intval($variation_id), true);
                }
            }

            if (isset($this->update_data['background_process']) && $this->update_data['background_process'] === true) {
                $background_process = VariationBackgroundProcess::get_instance();
                $background_process->add_completed_task(1);
            }
        }
    }

    private function delete_by_ids()
    {
        if (!is_array($this->product_ids) || empty($this->product_ids[0])) {
            return false;
        }

        $variable_id = intval($this->product_ids[0]);
        if (empty($this->update_data['value'])) {
            return false;
        }

        if (count($this->update_data['value']) > $this->max_process_count && VariationBackgroundProcess::is_enable()) {
            $background_process = VariationBackgroundProcess::get_instance();
            $this->is_processing = true;
            $grouped_ids = array_chunk($this->update_data['value'], $this->max_process_count);
            foreach ($grouped_ids as $key => $ids) {
                $background_process->push_to_queue([
                    'handler' => 'variation_delete',
                    'delete_class' => self::class,
                    'variable_id' => intval($variable_id),
                    'delete_data' => [
                        'type' => 'variation',
                        'name' => 'delete_variations',
                        'action' => 'delete_by_ids',
                        'value' => $ids,
                    ]
                ]);
            }
            $background_process->save();
            if (empty($this->update_data['background_process'])) {
                $background_process->set_total_tasks(count($this->update_data['value']));
            }
            $background_process->start();
        } else {
            foreach ($this->update_data['value'] as $variation_id) {
                wp_delete_post(intval($variation_id), true);

                if (isset($this->update_data['background_process']) && $this->update_data['background_process'] === true) {
                    $background_process = VariationBackgroundProcess::get_instance();
                    $background_process->add_completed_task(1);
                }
            }
        }

        return true;
    }

    private function delete_all()
    {
        global $wpdb;
        $product_ids = array_filter($this->product_ids, 'is_numeric');
        if (empty($product_ids)) {
            return false;
        }

        $placeholders = implode(',', array_fill(0, count($product_ids), '%d'));
        $sql = "
            SELECT COUNT(*) AS total 
            FROM {$wpdb->posts} 
            WHERE post_parent IN ($placeholders) 
            AND post_type = 'product_variation' 
            AND post_status != 'trash'
        ";

        $query = $wpdb->prepare($sql, ...$product_ids); //phpcs:ignore
        $count = $wpdb->get_row($query, ARRAY_A); //phpcs:ignore

        if (empty($count['total'])) {
            return false;
        }
        if (intval($count['total']) > $this->max_process_count && VariationBackgroundProcess::is_enable()) {
            $background_process = VariationBackgroundProcess::get_instance();
            $this->is_processing = true;
            $product_repository = Product::get_instance();
            foreach ($this->product_ids as $variable_id) {
                $variation_ids = $product_repository->get_product_variation_ids(intval($variable_id));
                if (empty($variation_ids) || !is_array($variation_ids)) {
                    continue;
                }
                $grouped_ids = array_chunk($variation_ids, $this->max_process_count);
                foreach ($grouped_ids as $key => $ids) {
                    $background_process->push_to_queue([
                        'handler' => 'variation_delete',
                        'delete_class' => self::class,
                        'variable_id' => intval($variable_id),
                        'delete_data' => [
                            'type' => 'variation',
                            'name' => 'delete_variations',
                            'action' => 'delete_by_ids',
                            'value' => $ids,
                        ]
                    ]);
                }
                $background_process->save();
            }
            if (empty($this->update_data['background_process'])) {
                $background_process->set_total_tasks(intval($count['total']));
            }
            $background_process->start();
        } else {
            foreach ($this->product_ids as $variable_id) {
                $this->do_delete_all($variable_id);
            }
        }

        return true;
    }

    private function do_delete_all($variable_id)
    {
        $product_repository = Product::get_instance();
        $variations = $product_repository->get_product_variation_ids(intval($variable_id));
        if (!empty($variations)) {
            foreach ($variations as $variation_id) {
                wp_delete_post(intval($variation_id), true);

                if (isset($this->update_data['background_process']) && $this->update_data['background_process'] === true) {
                    $background_process = VariationBackgroundProcess::get_instance();
                    $background_process->add_completed_task(1);
                }
            }
        }

        return true;
    }

    private function attribute_update($data)
    {
        if (!isset($data['product']) || !($data['product'] instanceof \WC_Product_Variable) || !isset($data['attribute']) || !isset($data['term'])) {
            return false;
        }

        $product_attributes = $data['product']->get_attributes();
        if (isset($product_attributes[$data['attribute']])) {
            if ($data['term'] == 'all_terms') {
                unset($product_attributes[$data['attribute']]);
            } else {
                if (
                    !empty($product_attributes[$data['attribute']])
                    && $product_attributes[$data['attribute']] instanceof \WC_Product_Attribute
                ) {
                    $term = get_term_by('slug', sanitize_text_field($data['term']), sanitize_text_field($data['attribute']));
                    if ($term instanceof \WP_Term) {
                        $options = $product_attributes[$data['attribute']]->get_options();
                        $option_key = array_search($term->term_id, $options);
                        if ($option_key !== false) {
                            unset($options[$option_key]);
                            $product_attributes[$data['attribute']]->set_options($options);
                        }
                    }
                }
            }

            $data['product']->set_attributes($product_attributes);
            return $data['product']->save();
        }

        return true;
    }
}
