<?php

namespace iwbvel\classes\services\product_update;

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

use iwbvel\classes\repositories\History;
use iwbvel\classes\services\product_update\variation_handlers\Add_Variations_Handler;
use iwbvel\classes\services\product_update\variation_handlers\Attach_Variation_Handler;
use iwbvel\classes\services\product_update\variation_handlers\Attributes_Edit_Handler;
use iwbvel\classes\services\product_update\variation_handlers\Default_Attributes_Handler;
use iwbvel\classes\services\product_update\variation_handlers\Delete_Variation_Handler;
use iwbvel\classes\services\product_update\variation_handlers\Replace_Variation_Handler;
use iwbvel\classes\services\product_update\variation_handlers\Swap_Variation_Handler;

class Variation_Update implements Update_Interface
{
    private static $instance;
    private $product_ids;
    private $update_data;
    private $save_history;
    private $is_processing;
    private $history_id;
    private $complete_actions;

    public static function get_instance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }

        return self::$instance;
    }

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

    public function set_update_data($data)
    {
        if (!isset($data['product_ids']) || empty($data['product_data']) || !is_array($data['product_data'])) {
            return false;
        }

        $this->product_ids = array_unique($data['product_ids']);
        $this->update_data = $data['product_data'];
        $this->complete_actions = (!empty($data['complete_actions'])) ? $data['complete_actions'] : null;
        $this->save_history = (!empty($data['save_history']));
        $this->history_id = 0;
        $this->is_processing = false;
    }

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

    public function perform()
    {
        if (empty($this->product_ids) || !is_array($this->product_ids) || empty($this->update_data) || !is_array($this->update_data)) {
            return false;
        }

        // save history
        if ($this->save_history) {
            $this->history_id = $this->save_history();
            if (empty($this->history_id)) {
                return false;
            }
        }

        foreach ($this->update_data as $update_data) {
            if (!isset($update_data['action'])) {
                continue;
            }

            if (!empty($this->history_id)) {
                $update_data['history_id'] = intval($this->history_id);
            }

            switch ($update_data['action']) {
                case 'add_variations':
                    $handler_class = Add_Variations_Handler::class;
                    break;
                case 'replace_variations':
                    $handler_class = Replace_Variation_Handler::class;
                    break;
                case 'attach_variations':
                    $handler_class = Attach_Variation_Handler::class;
                    break;
                case 'swap_variations':
                    $handler_class = Swap_Variation_Handler::class;
                    break;
                case 'delete_by_ids':
                case 'delete_by_term':
                case 'delete_all':
                    $handler_class = Delete_Variation_Handler::class;
                    break;
                case 'attributes_edit':
                    $handler_class = Attributes_Edit_Handler::class;
                    break;
                case 'default_attributes':
                    $handler_class = Default_Attributes_Handler::class;
                    break;
                default:
                    continue;
            }

            if (empty($handler_class)) {
                continue;
            }

            $instance = new $handler_class();
            $instance->update($this->product_ids, $update_data);
            $this->is_processing = $instance->is_processing();
        }

        if (!$this->is_processing && !empty($this->complete_actions)) {
            foreach ($this->complete_actions as $action) {
                if (!empty($action['hook'])) {
                    if (!empty($action['data'])) {
                        do_action($action['hook'], $action['data']); //phpcs:ignore
                    } else {
                        do_action($action['hook']); //phpcs:ignore
                    }
                }
            }
        }

        return true;
    }

    private function save_history()
    {
        $history_repository = History::get_instance();
        $fields = array_column($this->update_data, 'name');
        $this->history_id = $history_repository->create_history([
            'user_id' => intval(get_current_user_id()),
            'fields' => serialize($fields),
            'operation_type' => History::BULK_OPERATION,
            'operation_date' => gmdate('Y-m-d H:i:s'),
        ]);

        return $this->history_id;
    }
}
