<?php

namespace Hura8\Components\Product\Controller;

use Hura8\System\Url;
use Hura8\Components\Brand\Model\BrandModel;


class ProductFilterBuilderController {

    protected $_request_url = '';

    protected $_url_elements = [
        'scheme' => '',
        'host' => '',
        'port' => '',
        'user' => '',
        'pass' => '',
        'path' => '',
        'query' => [],
        'fragment' => '',
    ];

    protected $_price_format = '';
    protected $_brand_format = '';
    protected $_filter_format = '';


    public function __construct($request_url) {

        if(defined('PRICE_FILTER_FORMAT') && PRICE_FILTER_FORMAT) {
            $this->_price_format = PRICE_FILTER_FORMAT;
        }

        if(defined('BRAND_FILTER_FORMAT') && BRAND_FILTER_FORMAT) {
            $this->_brand_format = BRAND_FILTER_FORMAT;
        }

        if(defined('ATTRIBUTE_FILTER_FORMAT') && ATTRIBUTE_FILTER_FORMAT ) {
            $this->_filter_format = ATTRIBUTE_FILTER_FORMAT;
        }

        $this->_request_url = $request_url;
        $this->_url_elements = Url::parse($request_url);
    }


    public function buildProductFilterFromUrl(array $existing_filters = []) {
        $filters = [
            "price"         => $this->getPriceFilterRange(),
            "brand"         => $this->getBrandFilter(), // array(1,2,3,)
            "collection"    => $this->getGenericFilter('collection'), // array(1,2,3,)
            "supplier"      => $this->getGenericFilter('supplier'), // array(1,2,3,)
            "rating"        => $this->getGenericFilter('rating'), // array(1,2,3,)
            "category"      => $this->getGenericFilter('category'), // array(1,2,3,)
            "status"        => array(),  // array(1,2,3,)
            "query"         => (isset($this->_url_elements['query']['q'])) ? $this->_url_elements['query']['q'] : '', // string search keyword
            "hotType"       => $this->getGenericFilter('hotType', 'string'),// array(saleoff | not | new)
            "attribute"     => $this->getAttributeFilter(), // array(1,2,3,)
            "ids"           => $this->getGenericFilter('ids'), // array(1,2,3,)
            "promotion"     => "",
            "storeId"       => $this->getGenericFilter('store'), // array(1,2,3,)
            "other_filter"  => $this->getGenericFilter('other_filter', 'string'), // array(in-stock, has-promotion etc...)
            "spec_group_id"   => $this->getGenericFilter('spec_group_id'),
        ];


        // debug_var(array_merge($filters, $existing_filters));
        if(sizeof($existing_filters)) {
            foreach ($existing_filters as $key => $values) {
                if(!isset($filters[$key])) continue;
                if(!$values) continue;

                if(is_array($values) && is_array($filters[$key])) {
                    $filters[$key] = array_merge($filters[$key], $values);
                }else{
                    $filters[$key] = $values;
                }
            }
        }

        return $filters ;
    }


    protected function getGenericFilter($url_para, $data_type='int') {
        $value = (isset($this->_url_elements['query'][$url_para])) ? $this->_url_elements['query'][$url_para] : '';

        if($data_type == 'int') {
            $safe_value = trim(preg_replace("/[^0-9_\-\,]/i", '', $value));
        }else{
            $safe_value = trim(preg_replace("/[^a-z0-9_\-\.\,]/i", '', $value));
        }

        if(!$safe_value) return [];

        $safe_value_list = explode(FILTER_VALUE_SEPARATOR, $safe_value);

        return array_values(array_filter($safe_value_list));
    }


    protected function getBrandFilter()
    {
        if($this->_brand_format == 'brand_index'){

            $objBrandModel = new BrandModel();

            $result = [];
            $brand_filters = $this->getGenericFilter('brand', 'string');

            foreach ($brand_filters as $_brand) {
                if(is_int($_brand)) {
                    $result[] = $_brand;
                }

                $brand_info = $objBrandModel->getInfoByUrl( $_brand);
                if(!$brand_info) continue;

                $result[] = $brand_info['id'];
            }

            return $result;
        }


        // default
        return $this->getGenericFilter('brand');
    }


    protected function getAttributeFilter(array $category_list_id = []) {

        if($this->_filter_format == 'filter_code') {

            $excluded_keys = [
                'q',
                'p',
                'min', 'max',
                'brand',
                'page',
                'request_path',
                'category',
                'supplier', 'collection',
                'ids',
                'filter',' hotType',
                'other_filter',
                'rating', 'price',
                // special ajax key
                'action','action_type', '_auto'
            ];
            $attr_filter_params = [];

            foreach ( $this->_url_elements['query'] as $key => $value) {
                if(in_array($key, $excluded_keys) || !$value) continue;

                $attr_filter_params[$key] =  explode(',', urldecode(urldecode($value)));
            }

            if(sizeof($attr_filter_params)) {

                $category_attributes = $this->getAttributesForCategory($category_list_id);
                //debug_var($category_attributes);

                $match_attr_value_ids = [];
                foreach ($attr_filter_params as $attr_filter_code => $attr_value_api_key_list) {

                    foreach ($category_attributes as $attribute) {
                        if($attribute['filter_code'] != $attr_filter_code) continue;

                        foreach ($attribute['value_list'] as $_index => $_value_info) {

                            foreach ($attr_value_api_key_list as $attr_value_api_key) {
                                if($_value_info['api_key'] == $attr_value_api_key) {
                                    $match_attr_value_ids[] = $_value_info['id'];
                                }
                            }
                        }
                    }
                }


                return $match_attr_value_ids;
            }
        }

        // default
        return $this->getGenericFilter('filter');
    }



    protected function getAttributesForCategory(array $category_ids){

        $category_att_id_list = array();
        $attr_query_cond = (sizeof($category_ids)) ? " AND category_id IN (".join(',', $category_ids).")  " : "";

        $query = $this->db->runQuery(" SELECT `attr_id`  FROM `idv_attribute_category` WHERE 1 ". $attr_query_cond);
        foreach ($this->db->fetchAll($query) as $rs ){
            $category_att_id_list[] = $rs['attr_id'];
        }

        if(!sizeof($category_att_id_list)) return array();

        $query = $this->db->query("
							SELECT 
								attval.id , 
								attval.attributeId , 
								attval.value ,  
								attval.api_key , 
								att.attribute_code , 
								att.filter_code
							FROM ".TB_ATTRIBUTE_VALUE." attval
							LEFT JOIN ".TB_ATTRIBUTE." att ON attval.attributeId = att.id
							WHERE att.id IN (".join(',', $category_att_id_list).") AND att.isSearch=1 
							ORDER BY attval.ordering DESC ");

        $attribute_list = [];

        foreach ($this->db->fetchAll($query) as $rs ){
            $att_value_id   = $rs['id'];
            $att_id         = $rs['attributeId'];

            $value_info = array(
                "id"        => $att_value_id,
                "api_key"   => $rs['api_key'],
            );

            if(!array_key_exists($att_id, $attribute_list)) {
                $attribute_list[$att_id] = [
                    "id"            => $att_id,
                    "code"          => $rs['attribute_code'],
                    "filter_code"   => $rs['filter_code'],
                    'value_list'    => [$value_info],
                ];
            }else{
                $attribute_list[$att_id]['value_list'][] = $value_info;
            }
        }


        return array_values($attribute_list);
    }


    // accept url format:
    // default: ?min=1000&max=20000
    // custom: ?p=15trieu-20-trieu
    protected function getPriceFilterRange(){
        // default format
        if($this->_price_format != 'p') {
            return array(
                "min" => isset($this->_url_elements['query']['min']) ? intval($this->_url_elements['query']['min']) : 0 ,
                "max" => isset($this->_url_elements['query']['max']) ? intval($this->_url_elements['query']['max']) : 0 ,
            );
        }

        // custom price range query
        $price_range_format = (isset($this->_url_elements['query']['p'])) ? $this->_url_elements['query']['p'] : ''; //  duoi-10trieu , 10ngan-2trieu, 3trieu-6trieu, tren-30trieu

        if(strpos($price_range_format, '-') === false) {
            return array(
                "min" => 0,
                "max" => 0,
            );
        }

        $unit_translation = [
            'ngan' => 1000,
            'trieu' => 1000000,
            'ty' => 1000000000,
        ];

        // duoi-10trieu, duoi-10ngan
        if(strpos($price_range_format, 'duoi-') !== false) {
            $unit_match = $this->findPriceUnitMatch(str_replace("duoi-", "", $price_range_format));
            return array(
                "min" => 0,
                "max" => $unit_match['number'] * $unit_translation[$unit_match['unit']],
            );
        }

        // tren-10trieu, tren-10ngan
        if(strpos($price_range_format, 'tren-') !== false) {
            $unit_match = $this->findPriceUnitMatch(str_replace("tren-", "", $price_range_format));
            return array(
                "min" => $unit_match['number'] * $unit_translation[$unit_match['unit']],
                "max" => 0,
            );
        }

        // 10ngan-2trieu, 3trieu-6trieu
        $parts = explode('-', $price_range_format);
        $min_part = $parts[0];
        $max_part = $parts[1];
        $min_match = $this->findPriceUnitMatch($min_part);
        $max_match = $this->findPriceUnitMatch($max_part);

        return [
            "min" => $min_match['number'] * $unit_translation[$min_match['unit']],
            "max" => $max_match['number'] * $unit_translation[$max_match['unit']],
        ];
    }


    protected function findPriceUnitMatch($str){
        $match = [];
        $pattern = "/^([\d]+)(ngan|trieu|ty)/i";
        if(preg_match($pattern, $str, $match)){
            return [
                "number" => $match[1],
                "unit" => $match[2],
            ];
        }
        return [
            "number" => 0,
            "unit" => 'trieu',
        ];
    }
}
