<?php

namespace Hilco\Models;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\DB;
use Mailchimp\Mailchimp;

/**
 * Class Promotion
 * @package Hilco\Models
 *
 * @property Collection|PromotionTrigger[] $triggers
 * @property Collection|PromotionAction[] $actions
 * @property Collection|PromotionView[] $views
 * @property Collection|PromotionCodeTrigger[] $codeTriggers
 * @property Collection|PromotionCustomerTrigger[] $customerTriggers
 * @property Collection|PromotionFreeItemAction[] $freeItemActions
 * @property Collection|PromotionItemDiscountAction[] $itemDiscountActions
 * @property Collection|PromotionOrderCommentAction[] $orderCommentActions
 * @property Collection|PromotionOrderDiscountAction[] $orderDiscountActions
 * @property Collection|PromotionShippingDiscountAction[] $shippingDiscountActions
 * @property Collection|Order[] $orders
 * @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',
        'auto_apply_cst',
        'autoship_enabled',
        'commit_sequence',
    ];
    protected $casts = [
        'enabled' => 'boolean',
        'auto_apply_cst' => 'boolean',
        'autoship_enabled' => 'boolean',
//        'start_date' => 'date',
//        'end_date' => 'datetime',
    ];

    protected static $morphMap = [
        'billingTrigger' => PromotionBillingTypeTrigger::class,
        'codeTrigger' => PromotionCodeTrigger::class,
        'currencyTrigger' => PromotionCurrencyTrigger::class,
        'currentOrderTrigger' => PromotionCurrentOrderTrigger::class,
        'customerCategoryTrigger' => PromotionCustomerCategoryTrigger::class,
        'customerTrigger' => PromotionCustomerTrigger::class,
        'itemQuantityTrigger' => PromotionItemQuantityTrigger::class,
        'klaviyoListTrigger' => PromotionKlaviyoListTrigger::class,
        'priceListTrigger' => PromotionPriceListTrigger::class,
        'sourceTrigger' => PromotionSourceTrigger::class,
        'freeItemAction' => PromotionFreeItemAction::class,
        'itemDiscountAction' => PromotionItemDiscountAction::class,
        'orderCommentAction' => PromotionOrderCommentAction::class,
        'orderDiscountAction' => PromotionOrderDiscountAction::class,
        'shippingAction' => PromotionShippingAction::class,
        'shippingDiscountAction' => PromotionShippingDiscountAction::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 shippingActions(): MorphToMany {
        return $this->morphedByMany(PromotionShippingAction::class, 'action', 'PromotionActions', 'promotion_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
     * @deprecated we should be deprecating usage of PromotionShippingDiscountActions in favor of PromotionShippingActions
     */
    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 getActionClassFromType($actionType) {
        return \Illuminate\Support\Arr::get(Relation::morphMap(), $actionType, $actionType);
    }

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

    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, $onlyAutoship = false) {
        if (is_null($webSilo)) $webSilo = b2b()->activeWebSilo();
        if (!$webSilo->allow_promotions) {
            return collect();
        }
        $result = Promotion::active();
        if ($onlyAutoship) {
            $result = $result->where('autoship_enabled', '=', 1);
        }
        if ($withTriggers) {
            $result = $result->with(['triggers','codeTriggers','customerTriggers']);
        }
        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');
    }

    /**
     * @deprecated defunct promo integration, Hilco no longer uses Mailchimp
     */
    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 '';
        }
    }

    /**
     * @deprecated defunct promo integration, Hilco no longer uses Mailchimp
     */
    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 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;
    }

    public function isAutoshipEnabled() {
        return $this->autoship_enabled == 1;
    }

    use HasCommitSequence;
}