<?php

namespace FiloBlu\Refilo\Model\Adapter;

use Elasticsearch\ClientBuilder;
use Exception;
use FiloBlu\Refilo\Helper\Data as HelperData;
use RuntimeException;

/**
 *
 */
class Elastic extends AbstractAdapter
{
    /**
     * @var HelperData
     */
    private $helperData;

    /**
     * @var array
     */
    private $excludeFromIndex = [
        'assets',
        'variants',
    ];

    /**
     * Mongo constructor.
     * @param HelperData $helperData
     */
    public function __construct(
        HelperData $helperData
    ) {
        $this->helperData = $helperData;
        $this->connect();
    }

    public function connect()
    {
        $hosts = [
            'https://elastic:xtxcw68fqlw7g77b2kzj2b2g@146.148.30.117:9200'
        //   "http://34.76.140.105:9200",
         // $this->helperData->getConfigValue('elastic/general/elastic_host'),         // IP + Port
        ];

        $this->_connection = ClientBuilder::create()           // Instantiate a new ClientBuilder
        ->setRetries(2)
            ->setSSLVerification(false)
            ->setHosts($hosts)      // Set the hosts
            ->build();
    }

    /**
     * @param $key
     * @param $objects
     * @param $collection
     * @param bool $insertMode
     * @param $mongoDatabase
     * @return mixed|void
     * @throws Exception
     */
    public function insert($key, $objects, $collection, $insertMode, $mongoDatabase)
    {
        $i = 1;
        $index_prefix = $this->helperData->getConfigValue('elastic/general/elastic_prefix');

        if ($index_prefix === '') {
            throw new RuntimeException('please specify a index prefix');
        }

        foreach ($objects as $object) {
            $params['body'][] = [
                'index' => [
                    '_index' => $index_prefix . '_' . $collection,
                    '_id'    => $object->{$key},
                    //'_type'  => '_doc',
                ]
            ];
            $item = (array)$object;
            unset($item[$key]);
            $params['body'][] = $item;

            if ($i % 1000 === 0) {
                $responses = $this->_connection->bulk($params);

                // erase the old bulk request
                $params = ['body' => []];

                // unset the bulk response when you are done to save memory
                unset($responses);
            }
            $i++;
        }

        try {
            if (!empty($params['body'])) {
                $responses = $this->_connection->bulk($params);
                if (PHP_SAPI === 'cli') {
                    print_r(count($responses['items']));
                }
            }
        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

    /**
     * @param $collection
     * @return bool
     * @throws Exception
     */
    public function checkIndex($collection)
    {
        $index_prefix = $this->helperData->getConfigValue('elastic/general/elastic_prefix');

        if ($index_prefix === '') {
            throw new RuntimeException('please specify a index prefix');
        }

        $params = [
            'index' => $index_prefix . '_' . $collection,
        ];

        try {
            $this->_connection->indices()->get($params);
            return true;
        } catch (Exception $e) {
            return false;
        }
    }

    /**
     * @param $key
     * @param $objects
     * @param $collection
     * @param bool $insertMode
     * @param $mongoDatabase
     * @return void
     */
    public function update($key, $objects, $collection, $insertMode, $mongoDatabase)
    {
        $i = 1;
        $index_prefix = $this->helperData->getConfigValue('elastic/general/elastic_prefix');

        if ($index_prefix === '') {
            throw new RuntimeException('please specify a index prefix');
        }

        foreach ($objects as $object) {
            $body = [
                'update' => [
                    '_index' => $index_prefix . '_' . $collection,
                    '_id'    => $object->{$key},
                    '_type'  => '_doc'
                ]
            ];

            $item = get_object_vars($object);

            if ($insertMode) {
                $params['body'][] = $body;
                $params['body'][] = [
                    'doc'           => [
                        'attributes' => null,
                        'filters'    => null,
                        'sortables'  => null,
                        'variants'   => null
                    ],
                    'doc_as_upsert' => false];
            }

            $params['body'][] = $body;
            unset($item[$key]);
            $params['body'][] = ['doc' => $item, 'doc_as_upsert' => $insertMode];

            if ($i % 1000 === 0) {
                try {
                    $responses = $this->_connection->bulk($params);
                } catch (Exception $e) {
                    echo $e->getMessage();
                }
                // erase the old bulk request
                $params = ['body' => []];

                // unset the bulk response when you are done to save memory
                unset($responses);
            }
            $i++;
        }

        try {
            if (!empty($params['body'])) {
                $responses = $this->_connection->bulk($params);
                if (PHP_SAPI === 'cli') {
                    print_r(count($responses['items']));
                }
            }
        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

    public function dropCollection($collection, $mongoDatabase)
    {
        return true;
    }

    /**
     * @param $store
     * @param $indexes_to_exclude
     * @return mixed
     * @throws Exception
     */
    public function ensureIndex($store, $indexes_to_exclude)
    {
        $index_prefix = $this->helperData->getConfigValue('elastic/general/elastic_prefix');

        if ($index_prefix === '') {
            throw new RuntimeException('please specify a index prefix');
        }
        $indexes = [];

        foreach ($this->excludeFromIndex as $idx) {
            $indexes[$idx]['enabled'] = false;
        }

        $indexes['autosuggests']['type'] = 'completion';
        $indexes['name']['type'] = 'text';
        $indexes['name']['copy_to'] = 'autosuggests';
        $indexes['name']['fields']['keyword']['type'] = 'keyword';

        $indexes['sku']['type'] = 'keyword';
        $indexes['id']['type'] = 'long';

        $mapping = [
            'enabled'           => true,
            '_source'           => [
                'enabled' => true,
            ],
            'dynamic_templates' => [
                [
                    'attributes' => [
                        'match_mapping_type' => 'string',
                        'path_match'         => 'attributes.*',
                        'mapping'            => [
                            'type'         => 'keyword',
                            'ignore_above' => 256
                        ]
                    ],
                ],
                [
                    'filters' => [
                        'match_mapping_type' => 'string',
                        'path_match'         => 'filters.*',
                        'mapping'            => [
                            'type'         => 'keyword',
                            'ignore_above' => 256
                        ]
                    ],
                ],
                [
                    'sortables' => [
                        'match_mapping_type' => 'string',
                        'path_match'         => 'sortables.*',
                        'mapping'            => [
                            'type'         => 'keyword',
                            'ignore_above' => 256
                        ]
                    ],
                ]
            ]
            ,
            'properties'        => $indexes
        ];

        $params = [
            'index' => $index_prefix . '_' . $store,
            'body'  => [
                'settings' => [
                    'index.priority'                      => '1',
                    'index.query.default_field'           => ['*'],
                    'index.refresh_interval'              => '1s',
                    'index.write.wait_for_active_shards'  => '1',
                    'index.mapping.total_fields.limit'    => '1000',
                    'index.blocks.read_only_allow_delete' => 'false',
                    'index.number_of_replicas'            => '0'
                ],
                // sulla 7.
             //   'mappings' =>  $mapping
               // sulla 6.0
                'mappings' => ['_doc' => $mapping]
            ]
        ];

        try {
            // $deleteParams = [
            //    'index' => $index_prefix . '_' . $store
            // ];
            //$this->_connection->indices()->delete($deleteParams);
            $this->_connection->indices()->create($params);
        } catch (Exception $e) {
            print_r($e->getMessage());
        }
    }

    /**
     * @param $store
     * @throws Exception
     */
    public function checkConsistency($store)
    {
        $index_prefix = $this->helperData->getConfigValue('elastic/general/elastic_prefix');

        if ($index_prefix === '') {
            throw new RuntimeException('please specify a index prefix');
        }

        $updateRequest = [
            'index'     => $index_prefix . '_' . $store,
            'type'      => '_doc',
            'conflicts' => 'proceed',
            'body'      => [
                'query'  => [
                    'bool' => [
                        'must_not' => [
                            'exists' => [
                                'field' => 'pricing*'
                            ]
                        ]
                    ]
                ],
                'script' => [
                    'source' => "ctx._source.docType=''",
                    'lang'   => 'painless'
                ]
            ]
        ];

        $results = $this->_connection->updateByQuery($updateRequest);
    }
}
