<?php

namespace Hilco\Models;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Mailchimp\Mailchimp;
use LogicException;

/**
 * Class Promotion
 * @package Hilco\Models
 *
 * @method static Builder active()
 */
class Promotion extends WebModel {
    protected $table = 'Promotions';
    protected $fillable = [
        'name',
        'start_date', 'end_date',
        'enabled',
        'cart_header', 'checkout_header',
        'cart_header_title', 'checkout_header_title',
        'homepage_banner_text', 'homepage_banner_link',
        'almost_header', 'almost_header_title',
        'task_excluded', 'task_priority',
        'mailchimp_campaign_id',
        'description',
        'commit_sequence'
    ];
    protected $casts = [
        'enabled' => 'boolean',
//        'start_date' => 'date',
//        'end_date' => 'datetime',
    ];

    protected static $morphMap = [
        'codeTrigger' => PromotionCodeTrigger::class,
        'customerTrigger' => PromotionCustomerTrigger::class,
        'currentOrderTrigger' => PromotionCurrentOrderTrigger::class,
        'currencyTrigger' => PromotionCurrencyTrigger::class,
//        'customerCategoryTrigger' => PromotionCustomerCategoryTrigger::class,
        'itemQuantityTrigger' => PromotionItemQuantityTrigger::class,
//        'jobsonProfileTrigger' => PromotionJobsonProfileTrigger::class,
//        'rewardsTierTrigger' => PromotionRewardsTierTrigger::class,
//        'salesRepTrigger' => PromotionSalesRepTrigger::class,
        'sourceTrigger' => PromotionSourceTrigger::class,
        'shippingDiscountAction' => PromotionShippingDiscountAction::class,
//        'carrierCodeAction' => PromotionCarrierCodeAction::class,
//        'carrierAccountAction' => PromotionCarrierAccountAction::class,
        'freeItemAction' => PromotionFreeItemAction::class,
//        'internalCommentAction' => PromotionInternalCommentAction::class,
        'itemDiscountAction' => PromotionItemDiscountAction::class,
        'orderCommentAction' => PromotionOrderCommentAction::class,
        'orderDiscountAction' => PromotionOrderDiscountAction::class,
        'priceListAction' => PromotionPriceListAction::class
    ];

    public function triggers() {
        return $this->hasMany(PromotionTrigger::class);
    }

    public function actions() {
        return $this->hasMany(PromotionAction::class);
    }

    public function views() {
        return $this->hasMany(PromotionView::class);
    }

    public function codeTriggers() {
        return $this->morphedByMany(PromotionCodeTrigger::class, 'trigger', 'PromotionTriggers','promotion_id');
    }

    public function customerTriggers() {
        return $this->morphedByMany(PromotionCustomerTrigger::class, 'trigger', 'PromotionTriggers', 'promotion_id');
    }

    public function freeItemActions() {
        return $this->morphedByMany(PromotionFreeItemAction::class, 'action', 'PromotionActions', 'promotion_id');
    }

    public function itemDiscountActions() {
        return $this->morphedByMany(PromotionItemDiscountAction::class, 'action', 'PromotionActions', 'promotion_id')
            ->withPivot(['sequence'])
            ;
    }

    public function orderCommentActions() {
	return $this->morphedByMany(PromotionOrderCommentAction::class, 'action', 'PromotionActions', 'promotion_id');
    }

    public function orderDiscountActions() {
        return $this->morphedByMany(PromotionOrderDiscountAction::class, 'action', 'PromotionActions', 'promotion_id')
            ->withPivot(['sequence'])
            ;
    }

    public function priceListActions() {
        return $this->morphedByMany(PromotionPriceListAction::class, 'action', 'PromotionActions', 'promotion_id');
    }

    public function shippingDiscountActions() {
        return $this->morphedByMany(PromotionShippingDiscountAction::class, 'action', 'PromotionActions', 'promotion_id')
            ->withPivot(['sequence'])
            ;
    }

    public function getAllActionsAttribute() {
        return collect([
            $this->itemDiscountActions->flatten(),
        ])->flatten();
    }

//    public static function getTriggerClassFromType($triggerType) {
//        return \Illuminate\Support\Arr::get(Relation::morphMap(), $triggerType, $triggerType);
//    }
//
//    public static function createTriggerFromType($triggerType) {
//        $class = self::getTriggerClassFromType($triggerType);
//        return new $class;
//    }
//
//    public static function findTriggerFromType($triggerType, $triggerId) {
//        $class = self::getTriggerClassFromType($triggerType);
//        return $class::find($triggerId);
//    }
//
//    public function getTriggerRelationFromType($triggerType) {
//        $relationName = $triggerType . 's';
//        $relation = $this->$relationName();
//        return $relation;
//    }

    public static function getActionClassFromType($actionType) {
        return \Illuminate\Support\Arr::get(Relation::morphMap(), $actionType, $actionType);
    }

    public static function createActionFromType($actionType) {
        $class = self::getActionClassFromType($actionType);
        return new $class;
    }

//    public static function findActionFromType($actionType, $actionId) {
//        $class = self::getActionClassFromType($actionType);
//        return $class::find($actionId);
//    }

    public function getActionRelationFromType($actionType) {
        $relationName = $actionType . 's';
        $relation = $this->$relationName();
        return $relation;
    }
    
    public function scopeActive($query) {
        $query
            ->where('enabled', 1)
            ->where(function ($query) {
                return $query
                    ->where('start_date', '=', '0000-00-00 00:00:00')
                    ->orWhere('start_date', '<=', DB::raw('DATE(NOW())'))
                    ;
            })
            ->where(function ($query) {
                return $query
                    ->where('end_date', '=', '0000-00-00 00:00:00')
                    ->orWhere('end_date', '>=', DB::raw('DATE(NOW())'))
                    ;
            })
        ;
    }

    public static function getMorphMap() {
        return self::$morphMap;
    }

    public static function getActivePromotions($webSilo = null, $withTriggers = true) {
        if (is_null($webSilo)) $webSilo = b2b()->activeWebSilo();
        if (!$webSilo->allow_promotions) {
            return collect();
        }
        $result = Promotion::active();
        if ($withTriggers) {
            $result = $result->with([
                    'triggers','actions',
                    'codeTriggers','customerTriggers',
                    'freeItemActions','itemDiscountActions','orderCommentActions','orderDiscountActions','shippingDiscountActions'
                ]);
        }
        return $result->get();
    }

    public function getStartDateDatepickerAttribute() {
        $date = ($this->attributes['start_date'] == '0000-00-00') ? Carbon::now() : Carbon::createFromFormat('Y-m-d', $this->attributes['start_date']);

        return $date->format('Y-m-d');
    }

    public function getEndDateDatepickerAttribute() {
        $date = ($this->attributes['end_date'] == '0000-00-00') ? Carbon::now()->addYear(1) : Carbon::createFromFormat('Y-m-d', $this->attributes['end_date']);

        return $date->format('Y-m-d');
    }

    public function mailchimpCampaignName() {
        if ($this->mailchimp_campaign_id) {
            $mailchimp = new Mailchimp(config('mailchimp.apikey'));
            $campaign = $mailchimp->get('campaigns/' . $this->mailchimp_campaign_id);
            $fieldArray = $campaign->toArray();
            return $fieldArray['settings']->title;
        } else {
            return '';
        }
    }

    public function mailchimpCampaign() {
        if ($this->mailchimp_campaign_id) {
            $mailchimp = new Mailchimp(config('mailchimp.apikey'));
            try {
                $campaign = $mailchimp->get('campaigns/' . $this->mailchimp_campaign_id);
                $fieldArray = $campaign->toArray();
                return $fieldArray;
            } catch (Exception $e) {
                return [];
            }
        } else {
            return [];
        }
    }

    public static function getMailChimpCampaigns() {
        $mailchimp = new Mailchimp(config('mailchimp.apikey'), []);
        try {
            $newArray = [];
            $newArray[''] = '';
            $campaignsCollect = collect($newArray);
            $offset = 0;
            $limit = 10;
            do {
                $campaigns = $mailchimp->request('campaigns', [
                    'fields' => 'campaigns.id,campaigns.settings.title',
                    'count' => $limit,
                    'offset' => $offset
                ]);
                $campaignsArray = $campaigns->toArray();

                $newArray = [];
                foreach ($campaignsArray as $key => $value) {
                    $newArray[$value->id] = $value->settings->title;
                    unset($campaignsArray[$key]);
                }
                natcasesort($newArray);
                $campaignsCollect = $campaignsCollect->union(collect($newArray));

                $offset += $limit;
            }
            while (count($campaigns) > 0);
            $arrayForSort = $campaignsCollect->toArray();
            natcasesort($arrayForSort);
            $campaignsCollect = collect($arrayForSort);
            return $campaignsCollect;
        } catch (\Exception $e) {
            echo ('could not return mailchimp campaigns');
            return collect();
        }
    }

    public function orders() {
        return $this->belongsToMany(Order::class,
                                    'Promotion_SalesOrder',
                            'promotion_id',
                            'salesorder_id')
                    ->wherePivot('applied', '=', 1);
    }

    public static function boot() {
        parent::boot();

        static::deleted(function (Promotion $promotion) {
            foreach ($promotion->triggers as $trigger) {
                $trigger->delete();
            }
            foreach ($promotion->actions as $action) {
                $action->delete();
            }
        });
    }

    public function getCartHeaderAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->cart_header;
        } else {
            return '';
        }
    }

    public function getCheckoutHeaderAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->checkout_header;
        } else {
            return '';
        }
    }

    public function getAlmostHeaderAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->almost_header;
        } else {
            return '';
        }
    }

    public function getCartHeaderTitleAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->cart_header_title;
        } else {
            return '';
        }
    }

    public function getCheckoutHeaderTitleAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->checkout_header_title;
        } else {
            return '';
        }
    }

    public function getAlmostHeaderTitleAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->almost_header_title;
        } else {
            return '';
        }
    }

    public function getHomepageBannerTextAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->homepage_banner_text;
        } else {
            return '';
        }
    }

    public function getHomepageBannerLinkAttribute() {
        $langCode = b2b()->activeLanguage();
        $promoView = $this->views()->where('language_code', $langCode)->first();
        if (isset($promoView)) {
            return $promoView->homepage_banner_link;
        } else {
            return '';
        }
    }

    public function getPromoCode() {
        $codeTrigger = $this->codeTriggers->first();
        return isset($codeTrigger) ? $codeTrigger->code : null;
    }

    use HasCommitSequence;
}