<?php
namespace Hilco\Models;
use Aws\S3\S3Client;
use DB;
use Carbon\Carbon;
use Hilco\Pricing\PriceHelper;
use HilcoUAC\Exports\ArrayExport;
use HilcoUAC\Http\Controllers\PriceChecksToolController;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Hilco\HasSharedCustomLoggingTrait;
use ZipArchive;
use Response;
use Excel;
use NumberFormatter;



class Datafeed extends WebModel {

    const SHORTNAME = "SHORTNAME";
    const STYLENUMBER = "STYLENUMBER";
    const SHORTNAME_NO_F = "SHORTNAME_NO_F";
    const STYLENUMBER_NO_F = "STYLENUMBER_NO_F";
    const SAFILO_STANDARD = "SAFILO_STANDARD";
    const UPC = "UPC";

    protected $table = 'Datafeeds';
    protected $fillable = [
        'id', 'name', 'customer_id',
        'includeImages', 'isWhitelist',
        'imageNameFormat', 'enabled'
    ];

//    public function brands()
//    {
//        return $this->belongsToMany(Brand::class, 'Datafeed_Brand', 'datafeed_id', 'brand_id');
//    }

    public function webattributefilters()
    {
        return $this->hasMany(Datafeed_WebAttribute::class);
    }

    public function customer() {
        return $this->belongsTo(Customer::class);
    }

    public function datafeedFields()
    {
        return $this->hasMany(DatafeedField_Datafeed::class)->orderBy('overrideOrder');
    }

    public function datafeed_webhierarchy()
    {
        return $this->hasMany(Datafeed_WebHierarchy::class);
    }

    public function datafeed_webcategory()
    {
        return $this->hasMany(Datafeed_WebCategory::class);
    }

    public function datafeed_webgroup()
    {
        return $this->hasMany(Datafeed_WebGroup::class);
    }

    public function datafeed_webcollection()
    {
        return $this->hasMany(Datafeed_WebCollection::class);
    }

    public function datafeed_webfamily()
    {
        return $this->hasMany(Datafeed_WebFamily::class);
    }

    public function getImageNameFormatAttribute(){
        if (!in_array($this->getOriginal('imageNameFormat'), [self::SHORTNAME, self::SHORTNAME_NO_F, self::STYLENUMBER, self::STYLENUMBER_NO_F, self::SAFILO_STANDARD, self::UPC])){
            return self::SHORTNAME;
        }else{
            return $this->getOriginal('imageNameFormat');
        }
    }

    public function imageNameFormatIsSelected($imageNameFormat){
        return $this->imageNameFormat === $imageNameFormat;
    }
    public function getImageWidthAttribute(){
        $imageWidth = intval($this->getOriginal('imageWidth'));
        if ($imageWidth <= 0){
            return -1;
        }else{
            return $imageWidth;
        }
    }

    public function getImageHeightAttribute(){
        $imageHeight = intval($this->getOriginal('imageHeight'));
        if ($imageHeight <= 0){
            return -1;
        }else{
            return $imageHeight;
        }
    }

    public function includesInventoryCode($inventoryCode){
        return in_array($inventoryCode, explode(",", $this->inventoryCodes));
    }

    public function includesRankCode($rankCode){
        return in_array($rankCode, explode(",", $this->rankCodes));
    }

    public function buildQuery(){

        $query = WebPart
            ::join('Parts', 'WebParts.part_id', '=', 'Parts.id')
            ->join('WebPart_WebFamily', 'WebParts.id', 'WebPart_WebFamily.webpart_id')
            ->join('WebFamilies', 'WebPart_WebFamily.webfamily_id', 'WebFamilies.id')
            ->join('WebFamily_WebCollection', 'WebFamily_WebCollection.webfamily_id', 'WebFamilies.id')
            ->join('WebCollections', 'WebFamily_WebCollection.webcollection_id', 'WebCollections.id')
            ->join('WebCollection_WebCategory', 'WebCollection_WebCategory.webcollection_id', 'WebCollections.id')
            ->join('WebCategories', 'WebCollection_WebCategory.webcategory_id', 'WebCategories.id')
            ->join('WebCategory_WebGroup', 'WebCategory_WebGroup.webcategory_id', 'WebCategories.id')
            ->join('WebGroups', 'WebCategory_WebGroup.webgroup_id', 'WebGroups.id')
            ->join('WebGroup_WebHierarchy', 'WebGroup_WebHierarchy.webgroup_id', 'WebGroups.id')
            ->join('WebHierarchies', 'WebGroup_WebHierarchy.webhierarchy_id', 'WebHierarchies.id')

            ->when($this->visibility == 'web', function ($query)  {
                $websilo = $this->customer->websilo;
                $plant = $this->customer->activeSegment->plant;
                $query->webVisible($websilo, $plant);
            })
            ->when(!$this->datafeed_webhierarchy->isEmpty(), function ($query) {
                $ids = [];
                $bindings = [];
                foreach($this->datafeed_webhierarchy as $datafeed_webhierarchy) {
                    $ids[] = $datafeed_webhierarchy->webhierarchy_id;
                    $bindings[] = "?";
                }
                if ($this->exclude_hierarchy == 0) {
                    $query->whereRaw("WebHierarchies.id in (".join(",", $bindings).")", $ids);
                } else {
                    $query->whereRaw("WebHierarchies.id not in (".join(",", $bindings).")", $ids);
                }

            })
            ->when(!$this->datafeed_webgroup->isEmpty(), function ($query) {
                $ids = [];
                $bindings = [];
                foreach($this->datafeed_webgroup as $datafeed_webgroup) {
                    $ids[] = $datafeed_webgroup->webgroup_id;
                    $bindings[] = "?";
                }
                if ($this->exclude_group == 0) {
                    $query->whereRaw("WebGroups.id in (" . join(",", $bindings) . ")", $ids);
                } else {
                    $query->whereRaw("WebGroups.id not in (" . join(",", $bindings) . ")", $ids);

                }
            })
            ->when(!$this->datafeed_webcategory->isEmpty(), function ($query) {
                $ids = [];
                $bindings = [];
                foreach($this->datafeed_webcategory as $datafeed_webcategory) {
                    $ids[] = $datafeed_webcategory->webcategory_id;
                    $bindings[] = "?";
                }
                if ($this->exclude_category == 0) {
                    $query->whereRaw("WebCategories.id in (".join(",", $bindings).")", $ids);
                } else {
                    $query->whereRaw("WebCategories.id not in (".join(",", $bindings).")", $ids);
                }

            })
            ->when(!$this->datafeed_webcollection->isEmpty(), function ($query) {
                $ids = [];
                $bindings = [];
                foreach($this->datafeed_webcollection as $datafeed_webcollection) {
                    $ids[] = $datafeed_webcollection->webcollection_id;
                    $bindings[] = "?";
                }
                if ($this->exclude_collection == 0) {
                    $query->whereRaw("WebCollections.id in (".join(",", $bindings).")", $ids);
                } else {
                    $query->whereRaw("WebCollections.id not in (".join(",", $bindings).")", $ids);
                }

            })
            ->when(!$this->datafeed_webfamily->isEmpty(), function ($query) {
                $ids = [];
                $bindings = [];
                foreach($this->datafeed_webfamily as $datafeed_webfamily) {
                    $ids[] = $datafeed_webfamily->webfamily_id;
                    $bindings[] = "?";
                }
                if ($this->exclude_family == 0) {
                    $query->whereRaw("WebFamilies.id in (".join(",", $bindings).")", $ids);
                } else {
                    $query->whereRaw("WebFamilies.not id in (".join(",", $bindings).")", $ids);
                }

            })
            ->when($this->autoship == 'yes', function ($query) {
                $query->whereRaw("WebParts.has_subscribe_and_save = 1");
            })
            ->when($this->autoship == 'no', function ($query) {
                $query->whereRaw("WebParts.has_subscribe_and_save = 0");
            })
            ->when($this->iny_prescription == 'yes', function ($query) {
                $query->whereRaw("WebFamilies.is_prescription = 1");
            })
            ->when($this->iny_prescription == 'no', function ($query) {
                $query->whereRaw("WebFamilies.is_prescription = 0");
            })
            ;

        if ($this->available_plants != '') {
            foreach(explode(",",$this->available_plants) as $plant) {
                $query = $query->whereRaw('exists (select 1 from Parts join InventoryItems on (InventoryItems.part_id = Parts.id and InventoryItems.deleted_at = 0) where Parts.id = WebParts.part_id and InventoryItems.plant = ? and part_stat != "Obsolete")', $plant);
            }    
        }

        foreach($this->webattributefilters as $attributeFilter) {
            $language_code = $attributeFilter->language_code;
            if ($language_code == 'default') {
                $language_code = $this->default_language;
            }
            $query = $query->where(function ($q) use ($attributeFilter, $language_code) {
                if ($attributeFilter->operator == 'equals') {
                    $q = $q->whereRaw('exists (select 1 from WebAttribute_WebPart
                                                                join WebModelTranslations on (translatable_type = "webAttributeValue" and column_name = "attribute_value" and translatable_id = WebAttribute_WebPart.id) 
                                                        where WebAttribute_WebPart.webpart_id = WebParts.id
                                                                and WebModelTranslations.`language` = ?
                                                                and WebAttribute_WebPart.webattribute_id = ?
                                                                and WebModelTranslations.translation = ?
                                                                and WebAttribute_WebPart.deleted_at = 0
                                                                and exists (select 1 from WebAttribute_WebFamily
                                                                                    where WebAttribute_WebFamily.webfamily_id = WebFamilies.id
                                                                                    and WebAttribute_WebFamily.webattribute_id = WebAttribute_WebPart.webattribute_id
                                                                                    and WebAttribute_WebFamily.deleted_at = 0
                                                                            )
                                                )', [$language_code, $attributeFilter->webattribute_id, $attributeFilter->value]);
                } else if ($attributeFilter->operator == 'notequal') {
                    $q = $q->whereRaw('exists (select 1 from WebAttribute_WebPart
                                                                join WebModelTranslations on (translatable_type = "webAttributeValue" and column_name = "attribute_value" and translatable_id = WebAttribute_WebPart.id)
                                                        where WebAttribute_WebPart.webpart_id = WebParts.id
                                                                and WebModelTranslations.`language` = ?
                                                                and WebAttribute_WebPart.webattribute_id = ?
                                                                and WebModelTranslations.translation != ?
                                                                and WebAttribute_WebPart.deleted_at = 0
                                                                and exists (select 1 from WebAttribute_WebFamily
                                                                                    where WebAttribute_WebFamily.webfamily_id = WebFamilies.id
                                                                                    and WebAttribute_WebFamily.webattribute_id = WebAttribute_WebPart.webattribute_id
                                                                                    and WebAttribute_WebFamily.deleted_at = 0
                                                                            )
                                                )', [$language_code, $attributeFilter->webattribute_id, $attributeFilter->value]);
                } else if ($attributeFilter->operator == 'contains') {
                    $q = $q->whereRaw('exists (select 1 from WebAttribute_WebPart
                                                                join WebModelTranslations on (translatable_type = "webAttributeValue" and column_name = "attribute_value" and translatable_id = WebAttribute_WebPart.id)
                                                        where WebAttribute_WebPart.webpart_id = WebParts.id
                                                                and WebModelTranslations.`language` = ?
                                                                and WebAttribute_WebPart.webattribute_id = ?
                                                                and WebModelTranslations.translation like ?
                                                                and WebAttribute_WebPart.deleted_at = 0
                                                                and exists (select 1 from WebAttribute_WebFamily
                                                                                    where WebAttribute_WebFamily.webfamily_id = WebFamilies.id
                                                                                    and WebAttribute_WebFamily.webattribute_id = WebAttribute_WebPart.webattribute_id
                                                                                    and WebAttribute_WebFamily.deleted_at = 0
                                                                            )
                                                )', [$language_code, $attributeFilter->webattribute_id, "%" . $attributeFilter->value . "%"]);
                } else if ($attributeFilter->operator == 'starts') {
                    $q = $q->whereRaw('exists (select 1 from WebAttribute_WebPart
                                                                join WebModelTranslations on (translatable_type = "webAttributeValue" and column_name = "attribute_value" and translatable_id = WebAttribute_WebPart.id)
                                                        where WebAttribute_WebPart.webpart_id = WebParts.id
                                                                and WebModelTranslations.`language` = ?
                                                                and WebAttribute_WebPart.webattribute_id = ?
                                                                and WebModelTranslations.translation like ?
                                                                and WebAttribute_WebPart.deleted_at = 0
                                                                and exists (select 1 from WebAttribute_WebFamily
                                                                                    where WebAttribute_WebFamily.webfamily_id = WebFamilies.id
                                                                                    and WebAttribute_WebFamily.webattribute_id = WebAttribute_WebPart.webattribute_id
                                                                                    and WebAttribute_WebFamily.deleted_at = 0
                                                                            )
                                                )', [$language_code, $attributeFilter->webattribute_id, $attributeFilter->value . "%"]);
                } else if ($attributeFilter->operator == 'ends') {
                    $q = $q->whereRaw('exists (select 1 from WebAttribute_WebPart
                                                                join WebModelTranslations on (translatable_type = "webAttributeValue" and column_name = "attribute_value" and translatable_id = WebAttribute_WebPart.id)
                                                        where WebAttribute_WebPart.webpart_id = WebParts.id
                                                                and WebModelTranslations.`language` = ?
                                                                and WebAttribute_WebPart.webattribute_id = ?
                                                                and WebModelTranslations.translation like ?
                                                                and WebAttribute_WebPart.deleted_at = 0
                                                                and exists (select 1 from WebAttribute_WebFamily
                                                                                    where WebAttribute_WebFamily.webfamily_id = WebFamilies.id
                                                                                    and WebAttribute_WebFamily.webattribute_id = WebAttribute_WebPart.webattribute_id
                                                                                    and WebAttribute_WebFamily.deleted_at = 0
                                                                            )
                                                )', [$language_code, $attributeFilter->webattribute_id, '%' . $attributeFilter->value]);
                }
                $q = $q->when($attributeFilter->must_exist == 0, function ($q2) use ($attributeFilter, $language_code) {
                    $q2->orWhereRaw('not exists (select 1 from WebAttribute_WebPart
                                                                    join WebModelTranslations on (translatable_type = "webAttributeValue" and column_name = "attribute_value" and translatable_id = WebAttribute_WebPart.id) 
                                                            where WebAttribute_WebPart.webpart_id = WebParts.id
                                                                    and WebModelTranslations.`language` = ?
                                                                    and WebAttribute_WebPart.webattribute_id = ?
                                                                    and WebAttribute_WebPart.deleted_at = 0
                                                                    and exists (select 1 from WebAttribute_WebFamily
                                                                                        where WebAttribute_WebFamily.webfamily_id = WebFamilies.id
                                                                                        and WebAttribute_WebFamily.webattribute_id = WebAttribute_WebPart.webattribute_id
                                                                                        and WebAttribute_WebFamily.deleted_at = 0
                                                                                )
                                                    )', [$language_code, $attributeFilter->webattribute_id]);
                });
                return $q;
            });
        }
        return $query;
    }

    public function createZip($datafeedjob = null)
    {
        $dataFeed = $this;
//        $logName = $this->option('log-name');
//        if (strlen($logName) <= 0){
//            $logName = $dataFeed->name;
//        }
        $this->configureLogging('datafeeds', $dataFeed->name);
        $this->notice("Running Datafeed $dataFeed->name");

        $tempDir = storage_path('datafeed_temp'.DIRECTORY_SEPARATOR);
        if(!is_dir($tempDir)){
            mkdir($tempDir, 0777, true);
        }

        $feedTempDir = $tempDir . $dataFeed->name . DIRECTORY_SEPARATOR;
        if(!is_dir($feedTempDir)){
            mkdir($feedTempDir, 0777, true);
        }

        $it = new RecursiveDirectoryIterator(storage_path('datafeed_temp'.DIRECTORY_SEPARATOR.$dataFeed->name.DIRECTORY_SEPARATOR), RecursiveDirectoryIterator::SKIP_DOTS);
        $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
        foreach($files as $file) {
            if ($file->isFile() && preg_match('/\.gitignore$/', $file->getFileName()) === 0){
                $this->debug("deleting ".$file->getRealPath());
                if (unlink($file->getRealPath()) === false){
                    $this->error("could not delete ".$file->getRealPath());
                }
            }
        }



        $localFilesPath = $feedTempDir;
        if(!is_dir($localFilesPath)){
            mkdir($localFilesPath, 0777, true);
        }


        $dataQuery = $dataFeed->buildQuery();

        $headers = array();
        $dataFeedFields = $dataFeed->datafeedFields()->where('enabled', '=', '1')->with('transformations')->with('datafeedfield.bindingRules')->with('bindingvalues.datafeedfieldbindingrule')->orderBy('overrideOrder')->get();

        $priceChecks = array();

        $dataQuery->addSelect('WebParts.part_id');

        $priceCustomerExists = false;
        $priceListExists = false;
        $discountExists = false;
        foreach($dataFeedFields as $datafeedField){
            array_push($headers, $datafeedField->fieldName);
            if ($datafeedField->datafeedfield->tableName == 'price') {
                if ($datafeedField->datafeedfield->columnName === 'base') {
                    $priceCustomerExists = true;
                } else if ($datafeedField->datafeedfield->columnName === 'list') {
                    $priceListExists = true;
                } else if ($datafeedField->datafeedfield->columnName === 'discount' || $datafeedField->datafeedfield->columnName === 'discountPercent'){
                    // Need base price for discounts
                    $priceCustomerExists = true;
                    $discountExists = true;
                }

                continue; // Price calculations are done farther down after the parts are fetched
            } else if (!str_starts_with($datafeedField->datafeedfield->rawValue, '#')) {
                $dataQuery->addSelect($datafeedField->selectValue);
            }

        }

        // TODO add order by
//            $dataQuery->orderBy('Brands.brandName', 'ASC')->orderBy('Styles.styleDesc', 'ASC');


        $this->debug("Running query: [{$dataQuery->toSql()}]");
        $this->debug("Bindings are: [".print_r($dataQuery->getBindings(),true)."]");
        $webParts = $dataQuery->get()->toArray();

        //Convert everything to an array because working with objects is cumbersome here
        $webPartsArray = array();
        foreach($webParts as $webPart) {
            $webPartsArray[] = (array)$webPart;
        }
        $webParts = $webPartsArray;

        // Okay we have to inject pricing in all jank-like

        if ($priceCustomerExists || $priceListExists ) {
            $customerSegment = $this->customer->customerSegment;
            $dummyCustomer = $this->customer->getDummyCustomer();
            $dummyCustomerSegment = $dummyCustomer->customerSegment;
            $pricelistConnection = PriceListSchema::getActivePriceListSchema()->getPriceListConnection();
            $m3DiscountCodes = M3DiscountCode::all()->pluck('discount_type', 'discount_code')->toArray();
            $discountBucketRecords = OGDIPO::on($pricelistConnection)->byDiscModel($customerSegment->getDiscountModel())->orderBy('DIPO', 'ASC')->get();

            $objectMappingRecord = CROBJC::on($pricelistConnection)->byPriceListTable($customerSegment->getPriceListTable())->first();
        }
        $count = 0;
        $count = 0;
        $max = count($webParts);

        if ($datafeedjob != null) {
            $datafeedjob->records_found = $max;
            $datafeedjob->save();    
        }
        


        foreach($webParts as $key => $webPart) {

            if ($datafeedjob != null) {
                $datafeedjob->records_processed = $count;
                $datafeedjob->save();    
            }
            
            $count++;
            echo "$count : $max\r";
            $this->debug("$count : $max");

            $part = Part::find($webPart['part_id']);
            if ($priceCustomerExists) {
                $price = PriceHelper::getPriceRecord($pricelistConnection,  $this->customer, $part, 1, $customerSegment, $objectMappingRecord);
                if ($discountExists) {
                    if ($price == null) {
                        $discount = null;
                    } else {
                        $discount = PriceHelper::calculateDiscountDataForItem($pricelistConnection, $this->customer, $part, 1, $price->getSalePrice(), $m3DiscountCodes, $customerSegment, $discountBucketRecords);
                    }

                }
            };
            if ($priceListExists) {
                $listprice = PriceHelper::getPriceRecord($pricelistConnection,  $dummyCustomer, $part, 1, $dummyCustomerSegment, $objectMappingRecord);
            }

            //TODO localize with everything else

            foreach ($dataFeedFields as $datafeedField) {
                $hasCurrencyFormatter = $datafeedField->currency_formatter !== "0";
                if ($hasCurrencyFormatter) {
                    $currencyFormatter = new NumberFormatter($datafeedField->currency_formatter, NumberFormatter::CURRENCY);
                }
                if ($datafeedField->datafeedfield->tableName == 'static') {
                    $webPart[$datafeedField->fieldName] = $datafeedField->static_text;
                }
                else if ($datafeedField->datafeedfield->tableName == 'price') {
                    if ($datafeedField->datafeedfield->columnName == 'base') {
                        if ($price != null) {
                            if ($hasCurrencyFormatter) {
                                $webPart[$datafeedField->fieldName] = $currencyFormatter->formatCurrency($price->getSalePrice(), $price->CUCD);
                            } else {
                                $webPart[$datafeedField->fieldName] = $price->getSalePrice();
                            }
                        } else {
                            $webPart[$datafeedField->fieldName] = "";
                        }
                    } else if ($datafeedField->datafeedfield->columnName == 'list') {
                        if ($listprice != null) {
                            if ($hasCurrencyFormatter) {
                                $webPart[$datafeedField->fieldName] = $currencyFormatter->formatCurrency($listprice->getSalePrice(), $listprice->CUCD);
                            } else {
                                $webPart[$datafeedField->fieldName] = $listprice->getSalePrice();
                            }
                        } else {
                            $webPart[$datafeedField->fieldName] = "";
                        }

                    } else if ($datafeedField->datafeedfield->columnName == 'discount') {
                        if ($discount != null && $price != null) {
                            $webPart[$datafeedField->fieldName] = "1";
                            $totalDiscount = 0;
                            foreach($discount as $bucket => $valueArray) {
                                $dia = $valueArray['DIA'.$valueArray["bucketNo"]];
                                if ($dia == "") {
                                    $dia = 0;
                                }
                                $totalDiscount += $dia;
                            }
                            if ($hasCurrencyFormatter) {
                                $webPart[$datafeedField->fieldName] = $currencyFormatter->formatCurrency($price->getSalePrice() - $totalDiscount, $price->CUCD);
                            } else {
                                $webPart[$datafeedField->fieldName] = $price->getSalePrice() - $totalDiscount;
                            }
                        } else {
                            $webPart[$datafeedField->fieldName] = "";
                        }

                    } else if ($datafeedField->datafeedfield->columnName == 'discountPercent') {
                        if ($discount != null && $price != null) {
                            $webPart[$datafeedField->fieldName] = "1";
                            $totalDiscount = 0;
                            foreach($discount as $bucket => $valueArray) {
                                $dia = $valueArray['DIA'.$valueArray["bucketNo"]];
                                if ($dia == "") {
                                    $dia = 0;
                                }
                                $totalDiscount += $dia;
                            }
                            $webPart[$datafeedField->fieldName] = $totalDiscount / $price->getSalePrice() * 100;
                        } else {
                            $webPart[$datafeedField->fieldName] = "";
                        }

                    } else if ($datafeedField->datafeedfield->columnName == 'currencyCodeList') {
                        if ($listprice != null) {
                            $webPart[$datafeedField->fieldName] = $listprice->CUCD;
                        } else {
                            $webPart[$datafeedField->fieldName] = "";
                        }
                    } else if ($datafeedField->datafeedfield->columnName == 'currencyCodeCustomer') {
                        if ($price != null) {
                            $webPart[$datafeedField->fieldName] = $price->CUCD;
                        } else {
                            $webPart[$datafeedField->fieldName] = "";
                        }
                    }

                }

                foreach($datafeedField->transformations as $transformation) {
                    $webPart[$datafeedField->fieldName] = $transformation->transform($webPart[$datafeedField->fieldName]);
                }
            }
            $webParts[$key] = $webPart;
        }

        if ($dataFeed->export_type == 'csv') {
            // Build the CSV
            $fileName = trim($dataFeed->filename) == '' ? $dataFeed->name : $dataFeed->filename;
            $filePath = $localFilesPath.$fileName.".csv";
            $csvDelimiter = $dataFeed->csv_delimiter == null || $dataFeed->csv_delimiter == '' ? "," : $dataFeed->csv_delimiter;
            if ($dataFeed->csv_includeHeader == 1) {
                $fileData = implode($csvDelimiter ,$headers)."\n";
            } else {
                $fileData = '';
            }

            foreach($webParts as $webPart) {
                $row = [];
                foreach ($headers as $columnName){
                    $row[] = str_replace('"', '\"', $webPart[$columnName]);
                }
                $fileData.= "\"".implode("\"$csvDelimiter\"", $row)."\"\n";
            }
            file_put_contents($filePath, $fileData);
        } else if ($dataFeed->export_type == 'xlsx') {
            // Build the XLSX
            $filePath = $localFilesPath.$dataFeed->name.".xlsx";
            $sheetName = trim($dataFeed->xlsx_sheetname) == '' ? 'data' : $dataFeed->xlsx_sheetname;
            $export = new ArrayExport($webParts, $sheetName, $headers);
            $export->resortArray();
            $fileName = trim($dataFeed->filename) == '' ? $dataFeed->name : $dataFeed->filename;
            $result = Excel::store($export, $dataFeed->name.DIRECTORY_SEPARATOR.$fileName.".xlsx", 'datafeed_temp');
        }
        

        $this->notice("Data written to $filePath");



        //TODO includeImages
        if($dataFeed->includeImages){
//            $imageQuery = $dataFeed->buildQuery(new Unit());
//            $imageQuery->select(["Units.*", "Styles.styleDesc", "Styles.italy_style_number", "Styles.productType", "Styles.brandCode"])
//                ->groupBy('Units.style', 'Units.color', 'Units.lensCode');
//            if($dataFeed->groupImagesByFrameType){
//                $imageQuery->orderBy('Styles.productType', 'DESC');
//            }elseif($dataFeed->groupImagesByCollection){
//                $imageQuery->orderBy('Styles.brandCode', 'ASC');
//            }
//
//            $unitObjects = $imageQuery->get();
//
//            if(!is_dir($localFilesPath."images/")){
//                mkdir($localFilesPath."images/", 0777, true);
//            }
//
//            $size = "/".$dataFeed->imageWidth ."/". $dataFeed->imageHeight;
//            $this->startProgressEstimate(count($unitObjects), "Proccessing Images. %d Possible images found.");
//            foreach($unitObjects as $unitObject){
//                $this->estimateProgress("Processing Image %d of %d. (%s%%%s)");
//
//                if ($dataFeed->includeFullColorImages || $dataFeed->includeStyleFullImages){
//                    $asset = $unitObject->webUnit->getPrimaryImage();
//                    if(isset($asset)){
//                        $assetKey = $asset->asset_key;
//                        if ($dataFeed->imageNameFormat === Datafeed::SHORTNAME || $dataFeed->imageNameFormat === Datafeed::SHORTNAME_NO_F){
//                            $styleFullImageName = str_replace(str_split('"\\ :?<>&|/.'), '_', $unitObject->styleDesc).".jpg";
//                        } else {
//                            $styleFullImageName = $unitObject->style.".jpg";
//                        }
//
//                        if ($dataFeed->includeFullColorImages || ($dataFeed->includeStyleFullImages && !file_exists($localFilesPath."images/".$styleFullImageName))) {
//                            $localImageDir = "images/";
//
//                            if ($dataFeed->groupImagesByCollection || $dataFeed->zipByBrand){
//                                $localImageDir .= $unitObject->brandCode . "/";
//                                @mkdir($localFilesPath . $localImageDir);
//                            }
//                            if ($dataFeed->groupImagesByFrameType){
//                                $localImageDir .= strtoupper($unitObject->productType) . "/";
//                                @mkdir($localFilesPath . $localImageDir);
//                            }
//
//                            try {
//                                $image = file_get_contents(config('safilo-api.product_image_url') . "/product/" . $assetKey . $size);
//                                $feedFileName = $assetKey;
//                                if ($dataFeed->imageNameFormat === Datafeed::SHORTNAME) {
//                                    $feedFileName = "F-" . str_replace(str_split('"\\ :?<>&|/.'), '_', $unitObject->styleDesc) . $unitObject->color . $unitObject->lensCode . ".jpg";
//                                } else if ($dataFeed->imageNameFormat === Datafeed::SHORTNAME_NO_F) {
//                                    $feedFileName = str_replace(str_split('"\\ :?<>&|/.'), '_', $unitObject->styleDesc) . $unitObject->color . $unitObject->lensCode . ".jpg";
//                                } else if ($dataFeed->imageNameFormat === Datafeed::STYLENUMBER) {
//                                    $feedFileName = "F-" . $unitObject->style . $unitObject->color . $unitObject->lensCode . ".jpg";
//                                } else if ($dataFeed->imageNameFormat === Datafeed::STYLENUMBER_NO_F) {
//                                    $feedFileName = $unitObject->style . $unitObject->color . $unitObject->lensCode . ".jpg";
//                                } else if ($dataFeed->imageNameFormat === Datafeed::SAFILO_STANDARD) {
//                                    $feedFileName = $unitObject->italy_style_number . $unitObject->color . $unitObject->lensCode . "_P00.jpg";
//                                } else if ($dataFeed->imageNameFormat === Datafeed::UPC) {
//                                    $feedFileName = $unitObject->upc . ".jpg";
//                                }
//
//                                if ($dataFeed->groupImagesBySku){
//                                    $localImageDir .= $unitObject->upc . "/";
//                                    @mkdir($localFilesPath . $localImageDir);
//                                }
//
//                                if ($dataFeed->includeFullColorImages) {
//                                    $this->debug("$feedFileName written locally");
//                                    file_put_contents($localFilesPath . $localImageDir . $feedFileName, $image, FILE_USE_INCLUDE_PATH);
//                                }
//
//                                if ($dataFeed->includeStyleFullImages && !file_exists($localFilesPath."images/".$styleFullImageName)) {
//                                    $this->debug("$styleFullImageName written locally");
//                                    file_put_contents($localFilesPath . "images/" . $styleFullImageName, $image, FILE_USE_INCLUDE_PATH);
//                                }
//                            } catch (Exception $e) {
//                                $this->warn("Exception occurred processing Unit $unitObject->id | $unitObject->style | $unitObject->italy_style_number | $unitObject->styleDesc | $unitObject->color | $unitObject->lensCode | $unitObject->upc (Likely an IO Error on the Image Server)");
//                                $this->warn($e->getMessage());
//                                $this->warn($e->getTraceAsString());
//                            }
//                        }
//                    }else{
//                        $this->debug("Unit $unitObject->id | $unitObject->style | $unitObject->italy_style_number | $unitObject->styleDesc | $unitObject->color | $unitObject->lensCode | $unitObject->upc |  does not have an image asset.");
//                    }
//                }
//            }
//
//            if($dataFeed->includeLogos){
//                if(!is_dir($localFilesPath."logos/")){
//                    mkdir($localFilesPath."logos/", 0777, true);
//                }
//                $webBrands = WebBrand::whereIn('WebBrands.brand_id', $dataFeed->brands()->pluck('Brands.id'))->get();
//                foreach ($webBrands as $webBrand){
//                    $asset = $webBrand->getPrimaryImage();
//                    if(isset($asset)){
//                        try{
//                            $assetKey = $asset->asset_key;
//                            $image = file_get_contents( config('safilo-api.product_image_url')."/brands/".$assetKey);
//                            file_put_contents($localFilesPath."logos/".$assetKey, $image);
//                            $this->debug("$assetKey written locally.");
//                        }catch (Exception $e) {
//                            $this->warn("Exception occurred processing Brand $webBrand->id | $webBrand->slug | $webBrand->name (Likely an IO Error on the Image Server)");
//                            $this->warn($e->getMessage());
//                            $this->warn($e->getTraceAsString());
//
//                        }
//                    }else{
//                        $this->warn("Brand $webBrand->id | $webBrand->slug | $webBrand->name does not have an image asset.");
//                    }
//                }
//            }else{
//                $this->notice("Skipping logo generation.");
//            }
        }

        if(!is_dir(storage_path("datafeed_zips/"))){
            mkdir(storage_path("datafeed_zips/"), 0777, true);
        }

        $localZipPath = storage_path('datafeed_zips/').$dataFeed->name.".zip";
        if (is_file($localZipPath)){
            @unlink($localZipPath);
        }

        $date = Carbon::now();
//        $cronTimezone = config('safilo-api.cron_timezone', 'UTC');
//        $date->settimezone($cronTimezone);

        $zip = new ZipArchive($localZipPath);
        if (TRUE === $ret = $zip->open($localZipPath, ZipArchive::CREATE)) {
            $it = new RecursiveDirectoryIterator($localFilesPath, RecursiveDirectoryIterator::SKIP_DOTS);
            $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);


            foreach($files as $file) {

                $splitByDirectory = explode(DIRECTORY_SEPARATOR, $file->getRealPath());
                $append = false;
                $delim = $relativePath = "";
                foreach ($splitByDirectory as $fileOrDirectory){
                    if ($append){
                        $relativePath .= $delim . $fileOrDirectory;
                        $delim = DIRECTORY_SEPARATOR;
                    }

                    if ($fileOrDirectory === $dataFeed->name){
                        $append = true;
                    }
                }

                $this->debug("adding {$file->getRealPath()} to zip as $relativePath");
                if ($file->isFile() && preg_match('/\.gitignore$/', $file->getFileName()) === 0){
                    $zip->addFile($file->getRealPath(), $relativePath);
                }
            }
            $zip->close();
            touch($localZipPath, $date->getTimestamp());
        }

        $it = new RecursiveDirectoryIterator($localFilesPath, RecursiveDirectoryIterator::SKIP_DOTS);
        $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
        foreach($files as $file) {
            if ($file->isFile() && preg_match('/\.gitignore$/', $file->getFileName()) === 0){
                $this->debug("deleting ".$file->getRealPath());
                if (unlink($file->getRealPath()) === false){
                    $this->error("could not delete ".$file->getRealPath());
                }
            }else if ($file->isDir()){
                if (rmdir($file->getRealPath()) === false){
                    $this->error("could not delete ".$file->getRealPath());
                }
            }

        }
        if(is_dir($localFilesPath)){
            rmdir($localFilesPath);
        }

        $this->notice("Begin uploading $dataFeed->name");
        $allGood = true;

        $awsConfig = config('aws.awsDatafeedBucket');
        $s3 = S3Client::factory([
            'key'     => $awsConfig['key'],
            'secret'  => $awsConfig['secret'],
            'region'  => $awsConfig['region'],
            'version' => 'latest',
        ]);
        $bucket = $awsConfig['bucket'];

        $result = $s3->putObject([
            'Bucket' => $bucket,
            'Key' => $this->name.'.zip',
            'SourceFile' => $localZipPath
        ]);

        //TODO Check if this worked I guess? Not sure how entirely

        if ($allGood){

        }

        $this->notice("$dataFeed->name complete");

        return $datafeedjob;
    }

    // All attributefilters that exist on the object that aren't in the provided list should be deleted
    public function pruneAttributeFilters($foundAttributeFilterUUIDs) {
        foreach ($this->webattributefilters as $webattributefilter) {
            if (!in_array($webattributefilter->uuid, $foundAttributeFilterUUIDs)) {
                $webattributefilter->delete();
                $webattributefilter->save();
            }
        }
    }

    // All transformations that exist on the object that aren't in the provided list should be deleted
    public function pruneTransformations($foundTransformationUUIDs) {
        foreach ($this->datafeedFields as $datafeedField) {
            foreach ($datafeedField->transformations as $transformation) {
                if (!in_array($transformation->uuid, $foundTransformationUUIDs)) {
                    $transformation->delete();
                    $transformation->save();
                }
            }
        }

    }

    // All fields that exist on the object that aren't in the provided list should be deleted
    public function pruneFields($foundFieldIds) {
        foreach ($this->datafeedFields as $datafeedField) {
            if (!in_array($datafeedField->id, $foundFieldIds)) {
                $datafeedField->delete();
                $datafeedField->save();
            }
        }
    }

    use HasSharedCustomLoggingTrait;

    public function hasAvailablePlant($plantCode) {
        foreach(explode(",",$this->available_plants) as $availablePlant) {
            if ($plantCode == $availablePlant) {
                return true;
            }
        }

        return false;
    }

}
