<?php

namespace OfficeBrain\Bundle\SolrBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use OfficeBrain\Bundle\SolrBundle\Helper\ProductHelper;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use OfficeBrain\Bundle\CoreBundle\Cache\RedisCacheService;

/**
 * Sync product Category data command
 *
 * @author OfficeBrain 4220 <info@officebrain.com>
 */
class SyncProductCommand extends ContainerAwareCommand
{
    CONST COMMAND_NAME = 'office_brain:solr:sync:product';
    CONST TUBE_PREFIX = 'product_';
    CONST PAGING_LIMIT = 10;
    CONST PRODUCT_CACHE_CLIENT = 'product';
    
    protected $isOnlyCache;
    protected $categoryName;
    protected $languageId;
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName(self::COMMAND_NAME)
            ->setDescription('Command to sync product data')
            ->addOption('projectId', null, InputOption::VALUE_REQUIRED, 'project Id')
            ->addOption('instanceId', null, InputOption::VALUE_OPTIONAL, 'project instance Id')
            ->addOption('culture', null, InputOption::VALUE_OPTIONAL, 'supported search culture')
            ->addOption('productId', null, InputOption::VALUE_OPTIONAL, 'Product id')
            ->addOption('offset', null, InputOption::VALUE_OPTIONAL, 'offset for command operation')
            ->addOption('supplierId', null, InputOption::VALUE_OPTIONAL, 'Valid supplier id if value all is given than will execute for all active supplier\'s ')
            ->addOption('refSupplierId', null, InputOption::VALUE_OPTIONAL, 'Valid ref supplier id if value all is given than will execute for all active supplier\'s ')
            ->addOption('distributorId', null, InputOption::VALUE_OPTIONAL, 'Valid distributor id if value all is given than will execute for all active distributor\'s ')
            ->addOption('isOnlyCache', null, InputOption::VALUE_OPTIONAL, 'Enter 1 as value which you want to add only redis cache of product.')

            ->addOption('productIds', null, InputOption::VALUE_OPTIONAL, 'Enter comma seperated product ids.');
    }
    
    public function init() {
    	$this->entityManager = $this->getContainer()->get('doctrine.orm.entity_manager');
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
    	$this->init();
        $offset = $input->getOption('offset', null);
        $culture = $input->getOption('culture');
        $this->isOnlyCache = $input->getOption('isOnlyCache', null);
        
        $productId =(int) $input->getOption('productId', null);
        $productIds = $input->getOption('productIds', null);
        $instanceId =(int) $input->getOption('instanceId', null);
        $GLOBALS['distributorID'] = (int) $input->getOption('distributorId', null);
        if(empty($instanceId))
        {
            $instanceId=1;
        }
        $GLOBALS['instanceId'] = $instanceId;
        
        
        $event = new GetResponseEvent($this->getContainer()->get('kernel'),  $this->getContainer()->get('request'), HttpKernelInterface::MASTER_REQUEST);
        $accessListener = $this->getContainer()->get('office_brain_access_management.access_configuration');
        $accessListener->PrepareAccessAndConfigurationRulesForException ($event );
         
        $supplierId = $input->getOption('supplierId', null);
        $this->supplierId = $supplierId;
        $refSupplierId = $input->getOption('refSupplierId', null);
        $projectId = $input->getOption('projectId', null);
        
        if(empty($projectId))
        {
          $output->writeln('=======>Project Id can not be empty<=======');
          return false;
        }
        
        $productSearchClient = $this->getContainer()->get('office_brain_solr.product_search');
        
        $solrProductManager =$this->getContainer()->get('office_brain_solr_product_mapping_manager');
        if ($culture !== null) {
            $productSearchClient->setSearchCulture($culture);
        }        

        $this->subShopThemeManager = $this->getContainer()->get('office_brain_subshop_theme_manager');
        
        $subShopInstanceMeta = $this->entityManager->getRepository('OfficeBrainSubShopBundle:SubshopInstanceMeta')->findByMetaKey('product_category', $instanceId);
        if($subShopInstanceMeta){
        	$this->categoryName = json_decode($subShopInstanceMeta->getMetaValue(), 'array');
        }
        $this->categoryIds = array_keys($this->categoryName['custom_label']);
        $this->language = $this->getContainer()->getParameter('language');
        $cultureSplit = explode("_",$culture);
        $this->languageId = isset($this->language[$cultureSplit[0]]['id'])?$this->language[$cultureSplit[0]]['id']:1;

        $filterArray=array();
        if($productId != null && is_int($productId))
        {
            $output->writeln("Solr updating for Product id - " . $productId);
            $filterArray['productId'] = $productId;
        }elseif ($productId == null && $productIds ==null && $refSupplierId != null && isset($offset) && $offset != null ) {
            $output->writeln("Solr updating for ref supplier id - " . $refSupplierId);
            $filterArray['refSupplierId'] = $refSupplierId;
        }
        elseif ($productId == null && $productIds ==null && $supplierId != null && isset($offset) && $offset != null ) {
            $output->writeln("Solr updating for supplier id - " . $supplierId);
            $filterArray['supplierId'] = $supplierId;
        }
        elseif ($productId == null && $supplierId == null && $refSupplierId == null && $productIds ==null) {
            if($offset===null)
            {
              $supplierData = ProductHelper::getSupplierProductListByProjectId($solrProductManager,$projectId, $culture, 0,0);
              $this->prepareSupplierBatch($output,$projectId, $instanceId,$culture,$supplierData);
            }
        } else {
            
            $filterArray = array();
            if (isset($productId) && $productId!=0) {
                $output->writeln("Solr updating for Product id - " . $productId);
                $filterArray['productId'] = $productId;
            }
            if (isset($productIds)) {
                $output->writeln("Solr updating for Product id - " . $productIds);
                $filterArray['productIds'] = $productIds;
            }
            if (isset($refSupplierId)) {
            	if ($offset === null) {
            		$filterArray1['refSupplierId'] = $refSupplierId;;
            
            		$supplierData = ProductHelper::getSupplierProductListByProjectId($solrProductManager,$projectId, $culture, 0,$refSupplierId);
            		$this->prepareSupplierBatch($output,$projectId, $instanceId,$culture,$supplierData,true);
            	} else {
            		$output->writeln("Solr updating for ref supplier id - " . $refSupplierId);
            		$filterArray['refSupplierId'] = $refSupplierId;
            	}
            }else if (isset($supplierId)) {
                if ($offset === null) {
                    $filterArray1['supplierId'] = strtolower($supplierId) == "all" ? 'all' : $supplierId;
                    
                    $supplierData = ProductHelper::getSupplierProductListByProjectId($solrProductManager,$projectId, $culture, $supplierId,0);
                    // This place can be used to initialize the supplier count
                    $this->prepareSupplierBatch($output,$projectId, $instanceId,$culture,$supplierData);
                } else {
                    $output->writeln("Solr updating for supplier id - " . $supplierId);
                    $filterArray['supplierId'] = $supplierId;
                }
            }
        }
        if (count($filterArray) > 0) {
            if (isset($offset)) {
              
                $this->runBatchSync($productSearchClient,$projectId, $instanceId, $offset, self::PAGING_LIMIT, $filterArray, $culture);
            } else {
                $this->runBatchSync($productSearchClient,$projectId, $instanceId, 0, 0, $filterArray, $culture);
            }
            $output->writeln("Memory Usage - " . (memory_get_usage() / 1048576) . " MB");
            $output->writeln("----Command Completed-----");
            $this->statsh_cache_wrapper = RedisCacheService::create();
            $this->moduleCachePrefix = '__SiteModuleHomePage__';
            RedisCacheService::removeCacheByPrefix($this->statsh_cache_wrapper,$this->moduleCachePrefix);

            $this->moduleCachePrefix='__ProductTagManagement__';
            RedisCacheService::removeCacheByPrefix($this->statsh_cache_wrapper,$this->moduleCachePrefix);
            RedisCacheService::removeCacheByPrefix($this->statsh_cache_wrapper,'cunique');
            
            /* Update the status key and set it to zero */
            $em = $this->getContainer()->get('doctrine')->getManager();
            if ($em->getConnection()->ping() === false) {
            	$em->getConnection()->close();
            	$em->getConnection()->connect();
                $em->clear();
            }
            /*
            $this->subShopThemeManager->setSubShopInstanceKey('solr_sync_status_of_supplier_'.$supplierId, false, $instanceId);*/
        }
        else {
            //$output->writeln('\n\n=====No record found for batch processing=====');
            return;
        }
    }


    private function prepareSupplierBatch(OutputInterface $output,$projectId, $instanceId=1,$culture,$supplierData=array(),$usingRefSupplierId = false)
    {
        $totalBatch = count($supplierData);
        $env = $this->getContainer()->getParameter("kernel.environment");
        if($totalBatch==0)
        {
           $output->writeln('=====No record found for batch processing=====');
           return;
        }
        $output->writeln('-----------Total Batch is in put queue for process ' . $totalBatch . '-----------');
        $batchCount=$totalBatch;
        foreach ($supplierData as $key => $supplier) {
			// Update the total
			
        	$em = $this->getContainer()->get('doctrine')->getManager();
        	if ($em->getConnection()->ping() === false) {
        		$em->getConnection()->close();
        		$em->getConnection()->connect();
        	}
        	
        	if(isset($supplier['supplier_id']) && $supplier['supplier_id'] > 0)
        	{
        		$this->subShopThemeManager->newThenAddElseSetSubShopInstanceKey('solr_sync_status_of_supplier_'.$supplier['supplier_id'].'_'.$culture, $supplier['product_count'], $instanceId);
        	}
        	
            $output->writeln("\n\n");
            if(!$usingRefSupplierId){
            	$output->writeln("Supplier Id - " . $supplier['supplier_id']);
            }else{
            	$output->writeln("Supplier Id Ref- " . $supplier['supplier_id_ref']);
            }
            $output->writeln("Total product to processed - " . $supplier['product_count']);
            $output->writeln("Runnig Batch Number - " . $batchCount);
            $output->writeln("Total Batch - " . $totalBatch);
            $RemaingBatch=$batchCount-1;
            $output->writeln("Remaing Batch - " . $RemaingBatch);

            if ($supplier['product_count'] > self::PAGING_LIMIT) {
                $range = range(0, $supplier['product_count'], self::PAGING_LIMIT);
            } else {
                $range = array(0);
            }
            $totalBatch = count($range);
            if(!$usingRefSupplierId){
            	$output->writeln("############################# internal batch start for supplier id " . $supplier['supplier_id'] . " #############################");
            }else{
            	$output->writeln("############################# internal batch start for ref supplier id " . $supplier['supplier_id_ref'] . " #############################");
            }

        foreach ($range as $offset) {
            $command = '/usr/bin/php ' . $this->getContainer()->get('kernel')->getRootDir() . '/console ' . self::COMMAND_NAME . ' --projectId='.$projectId. ' --offset=' . $offset;
            
            if(!$usingRefSupplierId){
            	$command .=' --supplierId=' . $supplier['supplier_id'];
            }else{
            	$command .=' --refSupplierId=' . $supplier['supplier_id_ref'];
			}
			
            if ($culture !== null) {
                $command .= ' --culture=' . $culture;
            }
            if ($this->isOnlyCache == 1) {
                $command .= ' --isOnlyCache=' . $this->isOnlyCache;
            }
            
            $command .= ' --instanceId='.$instanceId;
            $command .= ' --env="'.$env.'"';
            $command .= ' --no-debug';
            $output->writeln('Command is in process = ' . $command);
            passthru($command);
          }
          if(!$usingRefSupplierId){
          	$output->writeln("############################# internal batch End for supplier id " . $supplier['supplier_id'] . " #############################");
          } else {
          	$output->writeln("############################# internal batch End for ref supplier id " . $supplier['supplier_id_ref'] . " #############################");
          }
          $output->writeln("--------------------- " . ($batchCount-$RemaingBatch) . " Batch Completed and remaining batch is " . $RemaingBatch . " ----------------------");
          $batchCount--;
          
          // Update the zero
          
          $em = $this->getContainer()->get('doctrine')->getManager();
          if ($em->getConnection()->ping() === false) {
          	$em->getConnection()->close();
          	$em->getConnection()->connect();
          }
          
          if(isset($supplier['supplier_id']) && $supplier['supplier_id'] > 0)
          {
          	$this->subShopThemeManager->newThenAddElseSetSubShopInstanceKey('solr_sync_status_of_supplier_'.$supplier['supplier_id'].'_'.$culture, 0, $instanceId);
          }
      }
    }
    protected function runBatchSync($productSearchClient,$projectId=0, $instanceId, $start = 0, $limit = self::PAGING_LIMIT, $filterCriteria = array(),$commandCulture)
    { 
        $startAt = microtime(true);
        $em = $this->getContainer()->get('doctrine')->getManager();
        
        #$productGreenBookManager =$this->getContainer()->get('office_brain_greenbook_master_manager');
        $solrProductManager =$this->getContainer()->get('office_brain_solr_product_mapping_manager');
        
        $culture = $productSearchClient->getSearchCulture();
        $productTagManager =$this->getContainer()->get('office_brain_product_tag_manager');
        $productCampaignManager =$this->getContainer()->get('office_brain_product_campaign_manager');
        $productAdminManager =$this->getContainer()->get('office_brain_product_admin_manager');
        
        $productSearchClient->setSearchCulture($culture);
        //$productSearchClient->setSearchCulture($commandCulture);
        
        $update = $productSearchClient->getCreateUpdateInstance();

        //$returnObjectArray = ProductHelper::newProductData($productManager, $cultureID, false, $start, $limit, $filterCriteria );
        $returnObjectArray = ProductHelper::getProductData($solrProductManager, $culture, $instanceId, $start, $limit, $filterCriteria );
        //print_r($returnObjectArray);exit;
        $i = 0;
        try {
        	foreach ($returnObjectArray as $returnObject) {
        		
                $returnObject['culture'] = $culture;
                $returnObject['instance_id'] = $instanceId;
                if ((isset($returnObject['category']) && $returnObject['category'] != "" && count($returnObject['category'])>0) || true) {
                    if (isset($returnObject['basic_information']) && $returnObject['basic_information']['active']==true && $returnObject['basic_information']['sku_number'] != "") {
                    	if(count($this->categoryIds)>0 && count($returnObject['category'])>0){
                    		foreach ($returnObject['category'] as $catId=>$catName) {
                    			if(in_array($catId,$this->categoryIds)) {
                    				$returnObject['category'][$catId] = $this->categoryName['custom_label'][$catId][$this->languageId];
                    			}
                    		}
                    	}
                    	
                        $this->createCache($returnObject,$projectId);

                        if($this->isOnlyCache!=1){
                          ProductHelper::generateKeyword($returnObject);
                          ProductHelper::setProductPricing($returnObject);
                          
                          ProductHelper::setProductGroupPricing($returnObject); 
                          ProductHelper::setProductAttributes($returnObject);
                          //ProductHelper::setPriceCurrency($returnObject);
  
                          //ProductHelper::generateCustomSortOrder($returnObject);
  
                          ProductHelper::setPublicCustomTag($productTagManager,$returnObject,$culture);
                          
                          ProductHelper::setCampaignProduct($productCampaignManager,$returnObject,$culture);
                          
                          ProductHelper::setProductOrder($productAdminManager,$returnObject);
                          
                          ProductHelper::generatePrioritizeSupplierOrderNew($returnObject);
                          
                          //ProductHelper::setProductVariationAttributeMatrix($returnObject);
                          //ProductHelper::setProductVariationPricing($returnObject);
                          
                          //print_r($returnObject['variation_attribute_matrix']);exit;
                          $productSearchClient->createIndex($update, $returnObject, false);
                        }
                        $i++;
                    }
                    else {
                        $this->logCategoryIssue($returnObject);
                    }
                } else {
                    $this->logCategoryIssue($returnObject);
                }
            }

            echo $i . ' Processed successfully' . "\n";
            
            if(isset($this->supplierId) && $this->supplierId > 0)
            {
            	/* Update the status key and set it to zero */
            	$em = $this->getContainer()->get('doctrine')->getManager();
            	if ($em->getConnection()->ping() === false) {
            		$em->getConnection()->close();
            		$em->getConnection()->connect();
            	}
            	$subshopInstanceMeta = $this->subShopThemeManager->getSubShopInstanceKey('solr_sync_status_of_supplier_'.$this->supplierId.'_'.$commandCulture, $instanceId);
            	if(is_object($subshopInstanceMeta))
            	{
            		$solrSyncStatusOfSupplier = $subshopInstanceMeta->getMetaValue();
            	}
            	else
            	{
            		$solrSyncStatusOfSupplier = 0;
            	}
            	
            	$solrSyncStatusOfSupplier = $solrSyncStatusOfSupplier - $limit;
            	
            	$this->subShopThemeManager->newThenAddElseSetSubShopInstanceKey('solr_sync_status_of_supplier_'.$this->supplierId.'_'.$commandCulture, $solrSyncStatusOfSupplier, $instanceId);
            }
            
            if($this->isOnlyCache!=1){
                $productSearchClient->commitBatch($update);
            }
        } catch (\Exception $e) {
            if ($limit != 0) {
                echo "Problem while updating command for batch number - " . ($limit != 0) ? ($start / $limit + 1) : "NA" . "\n";
                echo "star at " . $start . "\n";
            }
            echo "Error Message- " . $e->getMessage();
        }
        $time_taken = microtime(true) - $startAt;
        echo "Processing time: " . sprintf("%.4f", ($time_taken)) . " seconds\n";
    }

    /**
     * log Category issue
     * @param unknown $returnObject
     */
    public function logCategoryIssue($returnObject)
    {
        if(empty($returnObject['supplier']))return false;
        $logFilePath = $this->getContainer()->getParameter("kernel.logs_dir") . DIRECTORY_SEPARATOR . "category_" . $returnObject['culture'] ."_".$returnObject['supplier']['supplier_id']. ".csv";
        $active='in-active';
        if(isset($returnObject['basic_information']) && $returnObject['basic_information']['active']==true)
        {
          $active='active';
        }
        $array = array($returnObject['product_id']
        		, isset($returnObject['basic_information']) ? $returnObject['basic_information']['sku_number'] : ''
        		, $returnObject['supplier']['supplier_id']
        		, isset($returnObject['basic_information']) ? $returnObject['basic_information']['slug'] : ''
        		,$active);
        $fp = fopen($logFilePath, 'a+');
        fputcsv($fp, $array);
        fclose($fp);
    }

    public function sendToQueue($command, $culture)
    {
        $tubeName = self::TUBE_PREFIX . $culture;
        $pheanstalk = $this->getContainer()->get('leezy.pheanstalk');
        $pheanstalk->useTube($tubeName)->put($command);
    }
    
    public function createCache(&$returnObject, $projectId)
    {
        if(!RedisCacheService::isCacheEnable())
        {
            return null;
        }
        $cacheClient=RedisCacheService::create(null,self::PRODUCT_CACHE_CLIENT);
        
        $cacheKey11=RedisCacheService::generateKey($cacheClient,array($returnObject['product_id']
        		,"slug##"."*",$returnObject['culture']),'');
        
        $abc = RedisCacheService::removeCacheByPrefix($cacheClient,$cacheKey11);
        
        $cacheKey=RedisCacheService::generateKey($cacheClient,array($returnObject['product_id']
        		,"slug##".(isset($returnObject['basic_information'])?$returnObject['basic_information']['slug']:''),$returnObject['culture']),'');
        
        RedisCacheService::saveCacheData($cacheClient,$cacheKey,$returnObject);
    }
}