<?php

namespace Hilco\Models;

use Auth;
use Carbon\Carbon;
use DB;
use Debugbar;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Log;

/**
 * Hilco\Model\SubscriptionGroup
 * @property int $soldto_customer_id
 * @property int $createdby_webuser_id
 * @property int $lastmodifiedby_webuser_id
 * @property string $label
 * @property string $next_order_date
 * @property string $end_date
 * @property int $delayed_counter
 * @property int $subscriptionperiod_id
 * @property int $billto_customer_id
 * @property int $customershippingaddress_id
 * @property string $subscriptiongroup_type
 * @property Customer $soldToCustomer
 * @property WebUser $createdByWebUser
 * @property WebUser $modifiedByWebUser
 * @property Customer $billToCustomer
 * @property CustomerShippingAddress $customerShippingAddress
 * @property SubscriptionPeriod $subscriptionPeriod
 * @property Collection|SubscriptionItem[] $subscriptionItems
 * @property SubscriptionSubmissionRule $submissionRule
 * @property SubscriptionNotificationRule $notificationRules
 * @property Collection|Promotion[] $promotions
 */
class SubscriptionGroup extends UuidModel {
    protected $table = 'SubscriptionGroups';
    protected $fillable = ['subscriptiongroup_type'];

    public function soldToCustomer() {
        return $this->hasOne(Customer::class, 'id', 'soldto_customer_id');
    }

    public function billToCustomer() {
        return $this->hasOne(Customer::class, 'id', 'billto_customer_id');
    }

    public function customerShippingAddress() {
        return $this->hasOne(CustomerShippingAddress::class, 'id', 'customershippingaddress_id');
    }

    public function createdByWebUser() {
        return $this->hasOne(WebUser::class, 'id', 'createdby_webuser_id');
    }

    public function modifiedByWebUser() {
        return $this->hasOne(WebUser::class, 'id', 'lastmodifiedby_webuser_id');
    }

    public function subscriptionItems() {
        return $this->hasMany(SubscriptionItem::class, 'subscriptiongroup_id', 'id');
    }

    public function subscriptionPeriod() {
        return $this->hasOne(SubscriptionPeriod::class, 'id', 'subscriptionperiod_id');
    }

    /**
     * @deprecated see KlaviyoEvents::sendAutoshipKlaviyoEvent() in hilco-b2b project
     */
    public static function sendKlaviyoEventForSubscriptionGroup($eventName, $subscriptionGroup, $cartStatus, $changedItem = null, $error = null) {
        return;
//        $webSilo = $subscriptionGroup->modifiedByWebUser->customer->webSilo;
//        $client = new Klaviyo($webSilo->klaviyo_api_key, $webSilo->klaviyo_company_id);
//
//        $itemArray = [];
//        foreach($subscriptionGroup->subscriptionItems as $subscriptionItem) {
//            $itemArray[] = $subscriptionItem->getBaseItemWithPricesKlaviyoArray(
//                $cartStatus['items'][$subscriptionItem->id]['discountedPrice'],
//                $cartStatus['items'][$subscriptionItem->id]['discountedPrice']
//            );
//        }
//
//        if ($changedItem != null) {
//            $event = new KlaviyoEvent([
//                'event' => $eventName,
//                'customer_properties' => [
//                    '$id' => $subscriptionGroup->modifiedByWebUser != null ? $subscriptionGroup->modifiedByWebUser->id : '',
//                    '$email' => $subscriptionGroup->modifiedByWebUser != null ? $subscriptionGroup->modifiedByWebUser->email : ''
//                ],
//                'properties' => [
//                    'error_message' => $error != null ? $error : '',
//
//                    'group_name' => $subscriptionGroup->label,
//                    'next_order_date' => $subscriptionGroup->next_order_date,
//                    'cadence' => $subscriptionGroup->subscriptionPeriod->period_name,
//                    'delayed_counter' => $subscriptionGroup->delayed_counter,
//                    'group_type' => $subscriptionGroup->subscriptiongroup_type,
//
//                    'billto_customer_number' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->cust_no : '',
//                    'billto_customer_name' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->cust_name : '',
//                    'billto_addr_1' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_1 : '',
//                    'billto_addr_2' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_2 : '',
//                    'billto_addr_3' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_3 : '',
//                    'billto_addr_4' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_4 : '',
//                    'billto_addr_5' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_5 : '',
//                    'billto_city' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_city : '',
//                    'billto_state' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_state : '',
//                    'billto_zip' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_zip_postal : '',
//                    'billto_country' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_country : '',
//
//                    'shipto_addr_number' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_no : '',
//                    'shipto_customer_name' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->cust_name : '',
//                    'shipto_addr_1' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_1 : '',
//                    'shipto_addr_2' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_2 : '',
//                    'shipto_addr_3' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_3 : '',
//                    'shipto_addr_4' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_4 : '',
//                    'shipto_addr_5' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_5 : '',
//                    'shipto_city' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->city : '',
//                    'shipto_state' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->state : '',
//                    'shipto_zip' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->postal_cd : '',
//                    'shipto_country' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->country : '',
//
//                    'items' => $itemArray,
//                    'changedItem' => $changedItem,
//                    'discountTotal' => number_format($cartStatus['baseTotal'] - $cartStatus['discountedTotal'], 2),
//                    'taxAmount' => $cartStatus['taxAmount'],
//                    'orderTotal' => $cartStatus['orderTotal'],
//                ],
//            ]);
//        } else {
//            $event = new KlaviyoEvent([
//                'event' => $eventName,
//                'customer_properties' => [
//                    '$id' => $subscriptionGroup->modifiedByWebUser != null ? $subscriptionGroup->modifiedByWebUser->id : '',
//                    '$email' => $subscriptionGroup->modifiedByWebUser != null ? $subscriptionGroup->modifiedByWebUser->email : ''
//                ],
//                'properties' => [
//                    'error_message' => $error != null ? $error : '',
//
//                    'group_name' => $subscriptionGroup->label,
//                    'next_order_date' => $subscriptionGroup->next_order_date,
//                    'cadence' => $subscriptionGroup->subscriptionPeriod->period_name,
//                    'delayed_counter' => $subscriptionGroup->delayed_counter,
//                    'group_type' => $subscriptionGroup->subscriptiongroup_type,
//
//
//                    'billto_customer_number' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->cust_no : '',
//                    'billto_customer_name' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->cust_name : '',
//                    'billto_addr_1' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_1 : '',
//                    'billto_addr_2' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_2 : '',
//                    'billto_addr_3' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_3 : '',
//                    'billto_addr_4' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_4 : '',
//                    'billto_addr_5' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_addr_5 : '',
//                    'billto_city' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_city : '',
//                    'billto_state' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_state : '',
//                    'billto_zip' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_zip_postal : '',
//                    'billto_country' => $subscriptionGroup->billToCustomer != null ? $subscriptionGroup->billToCustomer->bill_country : '',
//
//                    'shipto_addr_number' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_no : '',
//                    'shipto_customer_name' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->cust_name : '',
//                    'shipto_addr_1' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_1 : '',
//                    'shipto_addr_2' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_2 : '',
//                    'shipto_addr_3' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_3 : '',
//                    'shipto_addr_4' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_4 : '',
//                    'shipto_addr_5' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->addr_5 : '',
//                    'shipto_city' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->city : '',
//                    'shipto_state' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->state : '',
//                    'shipto_zip' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->postal_cd : '',
//                    'shipto_country' => $subscriptionGroup->customerShippingAddress != null ? $subscriptionGroup->customerShippingAddress->country : '',
//
//                    'items' => $itemArray,
//                    'discountTotal' => number_format($cartStatus['baseTotal'] - $cartStatus['discountedTotal'], 2),
//                    'taxAmount' => $cartStatus['taxAmount'],
//                    'orderTotal' => $cartStatus['orderTotal'],
//                ],
//            ]);
//        }
//
//        $client->publicAPI->track($event);
    }

    public function orders() {
        return $this->belongsToMany(Order::class, 'SalesOrder_SubscriptionGroup', 'subscriptiongroup_id', 'salesorder_id');
    }

    public function getOrderCounterAttribute() {
        return $this->orders()->count();
    }

    public function scopeSubscriptiongroupType($query, $type) {
        $query->where('subscriptiongroup_type', $type);
    }

    public function calculateAndUpdateSubscriptionGroupType() {
        $type = 'default';
        foreach ($this->subscriptionItems as $item) {
            if (in_array(\Arr::get($item, 'part.item_type', ''), config('hilco.custom_item_types', ['D15']))) {
                $type = 'custom';
            }
        }
        $this->subscriptiongroup_type = $type;
        $this->save();
    }

    public function submissionRule() {
        return $this->hasOne(SubscriptionSubmissionRule::class, 'subscriptiongroup_type', 'subscriptiongroup_type');
    }

    public function notificationRules() {
        return $this->hasMany(SubscriptionNotificationRule::class, 'subscriptiongroup_type', 'subscriptiongroup_type');
    }

    public function getNextSubmissionDateAttribute() {
        $submissionRule = $this->submissionRule;
        if (is_null($submissionRule)) return false;

        if ($submissionRule->count_from == 'next_order_date') $sourceDate = Carbon::create($this->next_order_date);
        else $sourceDate = false;

        if ($sourceDate === false) return false;

        $counter = $submissionRule->count_days;
        while ($counter > 0) {
            if ($submissionRule->day_type === 'calendar') {
                $sourceDate = $sourceDate->subDay();
            } else if ($submissionRule->day_type === 'business') {
                $sourceDate = $sourceDate->subDay();
                while ($sourceDate->isWeekend()) {
                    $sourceDate = $sourceDate->subDay();
                }
            } else {
                return false;
            }

            $counter--;
        }

        return $sourceDate->toDateString();
    }

    public function getNextNotificationDatesAttribute() {
        $notificationRules = $this->notificationRules;
        if (is_null($notificationRules)) return [];

        $return = [];

        foreach ($notificationRules as $notificationRule) {

            if ($notificationRule->count_from === 'next_order_date') $sourceDate = Carbon::create($this->next_order_date);
            else if ($notificationRule->count_from === 'submission_date') $sourceDate = Carbon::create($this->next_submission_date);
            else $sourceDate = false;

            ///WHAT
            if ($sourceDate === false) {
                $return[$notificationRule->notification_type] = false;
                continue;
            }

            $counter = $notificationRule->count_days;
            while ($counter > 0) {
                if ($notificationRule->day_type === 'calendar') {
                    $sourceDate = $sourceDate->subDay();
                } else if ($notificationRule->day_type === 'business') {
                    $sourceDate = $sourceDate->subDay();
                    while ($sourceDate->isWeekend()) {
                        $sourceDate = $sourceDate->subDay();
                    }
                } else {
                    return false;
                }

                $counter--;
            }

            $return[$notificationRule->notification_type] = $sourceDate->toDateString();
        }

        return $return;
    }

    public function promotions(): BelongsToMany {
        return $this->belongsToMany(
            Promotion::class,
            'Promotion_SubscriptionGroup',
            "subscriptiongroup_id",
            "promotion_id"
        )->wherePivot("applied", "=", 1)->wherePivot("deleted_at", "=", "0000-00-00 00:00:00");
    }

    public function getHubSpotPropertiesForEvent ($eventName, $autoshipStatusObj, $changedItem = null, $errorMsg = ''): array {
        switch ($eventName) {
            case 'Subscription Created': {
                $groupProperties = $this->getHubSpotEventProperties($autoshipStatusObj);
                $groupProperties['value'] = $autoshipStatusObj['orderTotal'];
                $itemProps = $this->getAutoShipItemsForHubSpot($autoshipStatusObj, 2);
                return array_merge($groupProperties, $itemProps);
            }
            case 'Subscription Cancelled': {
                return array_merge(
                    $this->getHubSpotEventProperties($autoshipStatusObj),
                    $this->getAutoShipItemsForHubSpot($autoshipStatusObj, 2)
                );
            }
            case 'Subscription Item Back In Stock':
            case 'Subscription Item Discontinued':
            case 'Subscription Item Out of Stock': {
                $groupProperties = $this->getHubSpotEventProperties($autoshipStatusObj);
                $changedItemProps = [];
                if (isset($changedItem) && $changedItem instanceof SubscriptionItem) {
                    foreach ($autoshipStatusObj['items'] as $autoshipItem) {
                        $subscriptionItem = $autoshipItem['subscriptionItem'];
                        if ($subscriptionItem->int_id == $changedItem->int_id) {
                            $changedItemProps = $changedItem->getHubSpotEventProperties('changed_item', $autoshipItem, true, true);
                            break;
                        }
                    }
                }
                $itemProps = $this->getAutoShipItemsForHubSpot($autoshipStatusObj, 1);
                return array_merge($groupProperties, $changedItemProps, $itemProps);
            }
            case 'Subscription Price Updated': {
                $groupProperties = $this->getHubSpotEventProperties($autoshipStatusObj);
                $groupProperties['cadence_days'] = $this->subscriptionPeriod->days_cadence;
                if (isset($changedItem) && $changedItem instanceof SubscriptionItem) {
                    foreach ($autoshipStatusObj['items'] as $autoshipItem) {
                        $subscriptionItem = $autoshipItem['subscriptionItem'];
                        if ($subscriptionItem->int_id == $changedItem->int_id) {
                            $groupProperties['changed_item_current_unit_price'] = $autoshipItem['discountedPrice'];
                        }
                    }
                    $groupProperties['changed_item_previous_unit_price'] = $changedItem->last_calculated_price;
                }
                $itemProps = $this->getAutoShipItemsForHubSpot($autoshipStatusObj, 1, true, true);
                return array_merge($groupProperties, $itemProps);
            }
            case 'Subscription Skipped':
            case 'Subscription Pending': {
                return array_merge(
                    $this->getHubSpotEventProperties($autoshipStatusObj),
                    $this->getAutoShipItemsForHubSpot($autoshipStatusObj, 1)
                );
            }
            case 'Subscription Unsendable': {
                return array_merge(
                    $this->getHubSpotEventProperties($autoshipStatusObj, $errorMsg),
                    $this->getAutoShipItemsForHubSpot($autoshipStatusObj, 2)
                );
            }
            case 'Subscription Updated': {
                $groupProperties = $this->getHubSpotEventProperties($autoshipStatusObj);
                $groupProperties['value'] = $autoshipStatusObj['orderTotal'];
                $itemProps = [];
                if (isset($changedItem) && $changedItem instanceof SubscriptionItem) {
                    foreach ($autoshipStatusObj['items'] as $autoshipItem) {
                        $subscriptionItem = $autoshipItem['subscriptionItem'];
                        if ($subscriptionItem->int_id == $changedItem->int_id) {
                            $itemProps = $changedItem->getHubSpotEventProperties('changed_item', $autoshipItem);
                            break;
                        }
                    }
                }
                return array_merge($groupProperties, $itemProps);
            }
        }
        return [];
    }

    public function getHubSpotEventProperties ($autoshipStatusObj, $errorMsg = ''): array {//, $includeValue = false, $changedItem = null): array {
        $billTo = $this->billToCustomer;
        $shipToAddress = $this->customerShippingAddress;
        return [
            'bill_to_address_1'     => $billTo->bill_addr_1,
            'bill_to_address_2'     => $billTo->bill_addr_2,
            'bill_to_address_3'     => $billTo->bill_addr_3,
            'bill_to_city'          => $billTo->bill_city,
            'bill_to_country'       => $billTo->bill_country,
            'bill_to_customer_name' => $billTo->cust_name,
            'bill_to_customer_number' => $billTo->getCustNo(),
            'bill_to_state'         => $billTo->bill_state,
            'bill_to_zip'           => $billTo->bill_zip_postal,
            'cadence'               => $this->subscriptionPeriod->period_name,
            'delayed_counter'       => $this->delayed_counter,
            'discount_total'        => number_format($autoshipStatusObj['baseTotal'] - $autoshipStatusObj['discountedTotal'], 2),
            'error_message'         => $errorMsg,
            'group_name'            => $this->label,
            'group_type'            => $this->subscriptiongroup_type,
            'next_order_date'       => $this->next_order_date,
            'order_total'           => $autoshipStatusObj['orderTotal'],
            'origin'                => "Web",
            'ship_to_address_1'     => $shipToAddress->addr_1 ?? '',
            'ship_to_address_2'     => $shipToAddress->addr_2 ?? '',
            'ship_to_address_3'     => $shipToAddress->addr_3 ?? '',
            'ship_to_address_number' => $shipToAddress->addr_no,
            'ship_to_city'          => $shipToAddress->city ?? '',
            'ship_to_country'       => $shipToAddress->country ?? '',
            'ship_to_customer_name' => $shipToAddress->cust_name ?? '',
            'ship_to_state'         => $shipToAddress->state ?? '',
            'ship_to_zip'           => $shipToAddress->postal_cd ?? '',
            'tax_amount'            => $autoshipStatusObj['taxAmount']
        ];
    }

    public function getAutoShipItemsForHubSpot ($autoshipStatusObj, $maxItemIndex, $includeRefrig = false, $includeItemType = false): array {
        $max = $maxItemIndex;
        $index = 1;
        $prefix = "item_";
        $itemProperties = [];
        foreach ($autoshipStatusObj['items'] as $autoshipItem) {
            if ($index < $max+1) {
                $subscriptionItem = $autoshipItem['subscriptionItem'];
                $itemProperties = array_merge(
                    $itemProperties,
                    $subscriptionItem->getHubSpotEventProperties($prefix.$index, $autoshipItem, $includeRefrig, $includeItemType)
                );
                $index++;
            } else {
                break;
            }
        }
        return $itemProperties;
    }
}