<?php


namespace Hura8\System\Controller;

use Hura8\Database\ConnectDB;

abstract class aERPController implements iClientERP
{

    protected $provider;
    protected $erp_config;

    protected $tb_product            = TableName::PRODUCT;
    protected $tb_erp_product        = "erp_product";

    // this table is the exact copy of $tb_erp_product
    // it's used when call the syncProductToWeb method to make sure that no new products are added in the syncing process
    protected $tb_erp_product_copy   = "erp_product_tmp_copy";

    protected $tb_log           = "erp_log";

    /* @var $objERPProvider iERPProvider */
    protected $objERPProvider;

    /* @var $db ConnectDB */
    protected $db;

    protected $get_erp_product_options = [];


    public function __construct($provider)
    {
        $this->provider     = $provider;

        $provider_config_file = CONFIG_DIR . '/provider/'.$provider.'_config.php';
        if(file_exists($provider_config_file)) {
            $this->erp_config = include $provider_config_file;

            // create an instance of provider
            $this->erpFactory();

            $this->db = ConnectDB::getInstance('');
        }else{
            die("Cannot load /config/provider/".$provider."_config.php ");
        }
    }

    abstract protected function customSyncProductToWeb();
    abstract protected function formatProductListFromERP(array $product_list);

    /**
     * @overwrite on implemeting class if needed
     */
    public function getProductListPerPage($page, $debug = false) {
        return $this->getProductList(['page' => $page], $debug);
    }

    /**
     * @return iERPProvider
     */
    public function getERPInstance()
    {
        return $this->objERPProvider;
    }

    public function createOrder(array $order_info)
    {
        return $this->objERPProvider->createOrder($order_info);
    }

    /**
     * @param array $options
     */
    public function syncProductToWeb(array $options = [])
    {
        $this->beforeSyncProductToWeb();
        $this->customSyncProductToWeb();
        $this->afterSyncProductToWeb();
    }

    protected function beforeSyncProductToWeb() {
        /*$this->db->runQuery("CREATE TABLE `" . $this->tb_erp_product_copy . "` LIKE ".$this->tb_erp_product."  ");
        $this->db->runQuery("INSERT INTO `" . $this->tb_erp_product_copy . "` SELECT * FROM ".$this->tb_erp_product."  ");
        $this->db->runQuery("UPDATE `" . $this->tb_erp_product_copy . "` e, idv_sell_product_store p SET
                                    e.product_id = p.id
                            WHERE e.sku = p.storeSKU AND LENGTH(e.sku) > 0 ");
        $this->db->runQuery("DELETE FROM `" . $this->tb_erp_product_copy . "`  WHERE `product_id` = 0 ");*/

        $this->db->multi_query([
            "CREATE TABLE IF NOT EXISTS `" . $this->tb_erp_product_copy . "` LIKE ".$this->tb_erp_product."  ",
            "INSERT INTO `" . $this->tb_erp_product_copy . "` SELECT * FROM ".$this->tb_erp_product."  ",
            "UPDATE `" . $this->tb_erp_product_copy . "` e, ".$this->tb_product." p SET
                                    e.product_id = p.id
                            WHERE e.sku = p.storeSKU AND LENGTH(e.sku) > 0 ",
        ]);

    }

    protected function afterSyncProductToWeb() {
        $this->db->runQuery("DROP TABLE `" . $this->tb_erp_product_copy . "`  ");
    }

    public function setERPProductOptions(array $options = []) {
        foreach ($options as $key => $value) {
            $this->get_erp_product_options[$key] = $value;
        }
    }

    /**
     * @description: clean any existing data before populate new ones
     * @return void
     */
    public function cleanExistingData()
    {
        $this->db->runQuery("TRUNCATE `" . $this->tb_erp_product . "` ");
    }

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


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


    public function getProductList(array $options = [], $debug = false)
    {
        return $this->formatProductListFromERP($this->objERPProvider->getProductList($options, $debug));
    }


    /**
     * get log data
     */
    public function getLog($type, $limit = 50) {
        $query = $this->db->runQuery("SELECT `id`, `data`, `log_time` FROM `".$this->tb_log."` WHERE `type` = ? ORDER BY `id` DESC LIMIT ".$limit, ['s'], [$type]);

        return array_map(function ($item){
            $copy = $item;
            $copy['data'] = $item['data'] ? \json_decode($item['data'], true) : [];

            return $copy;
        }, $this->db->fetchAll($query));
    }

    /**
     * log data
     */
    public function updateLogData($id, $new_data) {

        $query = $this->db->runQuery("SELECT `data` FROM `".$this->tb_log."` WHERE `id` = ? LIMIT 1", ['d'], [$id]);

        if($item_info = $this->db->fetchAssoc($query)) {
            $current_data = $item_info['data'] ? \json_decode($item_info['data'], true) : [];
            $updated_info = array_merge($current_data, $new_data);

            return $this->db->update($this->tb_log, ['data' => $updated_info], ['id' => $id]);
        }

        return false;
    }

    /**
     * log data
     */
    public function log($type, array $data) {
        $info = [];
        $info['type'] = $type;
        $info['data'] = $data;
        $info['log_time'] = CURRENT_TIME;

        return $this->db->insert($this->tb_log, $info);
    }

    protected function erpFactory()
    {
        if(!$this->provider) {
            die("No provider found!");
        }

        $provider_class = 'Provider\\ERPProviders\\'.ucfirst($this->provider);

        try {

            $this->objERPProvider = (new \ReflectionClass($provider_class))->newInstance($this->erp_config);

        } catch (\ReflectionException $e) {
            die("aClientERP/erpFactory: ".$e->getMessage());
        }
    }

}
