<?php

namespace Hilco\Models;

use Carbon\Carbon;
use Hilco\SoftDeletes;
use Illuminate\Support\Facades\DB;

/**
 * Hilco\Models\Order
 *
 * @property mixed $id
 * @property mixed $division_id
 * @property mixed $plant_id
 * @property string $invoice_number
 * @property string $web_order_number
 * @property mixed $billto_customersegment_id
 * @property mixed $soldto_customersegment_id
 * @property string $fob
 * @property string $payment_terms
 * @property float $tax_amt
 * @property float $freight_amt
 * @property string $invoice_date
 * @property string $ship_date
 * @property Carrier $carrier
 * @property string $ship_via
 * @property string $customer_po
 * @property string $order_type
 * @property string $shipping_policy
 * @property string $date_created
 * @property string $date_modified
 * @property string $deleted_at
 * @property-read \Illuminate\Database\Eloquent\Collection|\Hilco\Models\OrderItem[] $items
 * @property-read \Illuminate\Database\Eloquent\Collection|\Hilco\Models\OrderMainLine[] $mainLines
 * @property-read mixed $affiliateSales
 * @property-read mixed $id_string
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereDivisionId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order wherePlantId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereInvoiceNumber($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereWebOrderNumber($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereBilltoCustomersegmentId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereSoldtoCustomersegmentId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereFob($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order wherePaymentTerms($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereTaxAmt($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereFreightAmt($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereInvoiceDate($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShipDate($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCarrier($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShipVia($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCustomerPo($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderType($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingPolicy($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereDateCreated($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereDateModified($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereDeletedAt($value)
 * @mixin \Eloquent
 * @property string $hilco_order_number
 * @property string $order_date
 * @property string $order_due_date
 * @property string $order_status
 * @property string $ship_policy
 * @property integer $salesordertype_id
 * @property integer $salesordersource_id
 * @property string $ship_to_attention
 * @property integer $fob_id
 * @property integer $carrier_id
 * @property integer $paymentterm_id
 * @property string $order_instructions
 * @property string $currency_code
 * @property integer $salesrep_id
 * @property integer $billto_customer_id
 * @property integer $soldto_customer_id
 * @property string $shipping_line1
 * @property string $shipping_line2
 * @property string $shipping_line3
 * @property string $shipping_city
 * @property string $shipping_state
 * @property string $shipping_zip
 * @property string $shipping_country
 * @property string $comment_all
 * @property string $comment_external
 * @property string $comment_internal
 * @property string $comment_display
 * @property float $part_amount
 * @property float $misc_amount
 * @property float $part_discount
 * @property float $order_discount
 * @property float $freight_amount
 * @property float $tax_amount
 * @property float $ins_amount
 * @property float $order_amount
 * @property string $order_source
 * @property string $order_origin
 * @property integer $reward_tier
 * @property string $promo_code
 * @property string $state_license
 * @property string $plant
 * @property string $warehouse
 * @property string $bin_location
 * @property string $date_uploaded
 * @property integer $warehouse_id
 * @property integer $binlocation_id
 * @property string $authorization_code
 * @property float $authorized_amount
 * @property string $auth_reference_num
 * @property integer $deliverymethod_id
 * @property integer $delivery_priority
 * @property integer $deliveryterm_id
 * @property integer $customershippingaddress_id
 * @property string $shipping_no
 * @property string $email
 * @property integer $webuser_id
 * @property float $header_discount_amount
 * @property float $header_discount_percent
 * @property string $header_discount_desc
 * @property string $header_discount_code
 * @property float $handling_amount
 * @property string $shipping_attnofname
 * @property integer $shippingpolicytype_id
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereHilcoOrderNumber($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderDate($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderDueDate($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderStatus($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShipPolicy($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereSalesordertypeId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereSalesordersourceId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShipToAttention($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereFobId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCarrierId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order wherePaymenttermId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderInstructions($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCurrencyCode($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereSalesrepId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereBilltoCustomerId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereSoldtoCustomerId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingLine1($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingLine2($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingLine3($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingCity($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingState($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingZip($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereShippingCountry($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCommentAll($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCommentExternal($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCommentInternal($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereCommentDisplay($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order wherePartAmount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereMiscAmount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order wherePartDiscount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderDiscount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereFreightAmount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereTaxAmount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereInsAmount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderAmount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereOrderSource($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereStateLicense($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order wherePlant($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereWarehouse($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereBinLocation($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereDateUploaded($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereWarehouseId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereBinlocationId($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereAuthorizationCode($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereAuthorizationAmount($value)
 * @method static \Illuminate\Database\Query\Builder|\Hilco\Models\Order whereAuthReferenceNum($value)
 * @property-read \Hilco\Models\Division $division
 * @property-read \Illuminate\Database\Eloquent\Collection|\Hilco\Models\SalesOrderLine[] $partLines
 * @property-read \Illuminate\Database\Eloquent\Collection|\Hilco\Models\OrderMainLine[] $miscLines
 * @property-read \Hilco\Models\Customer $soldToCustomer
 * @property-read \Hilco\Models\Customer $billToCustomer
 * @property-read \Hilco\Models\Plant $orderShipPlant
 * @property-read \Hilco\Models\Warehouse $orderShipWarehouse
 * @property-read \Hilco\Models\BinLocation $orderShipBinLocation
 * @property-read \Hilco\Models\Customer $customer
 * @property-read \Illuminate\Database\Eloquent\Collection|\Hilco\Models\OrderMainLine[] $orderParts
 * @property-read \Hilco\Models\SalesOrderSource $salesOrderSource
 */
class Order extends UuidModel
{
	protected $table = 'SalesOrders';

	public static $categories = [
		'overallsales' => '',
		'rxsales' => ['RX SAFETY'],
		'lenscaresales' => ['LC / BRANDING OTHER'],
		'consumersales' => ['ACCESSORIES OTHER'],
		'brandingsales' => ['LC / BRANDING OTHER'],
		'examinationsales' => ['EXAM SUPPLIES'],
		'customizationsales' => ['REPAIR PARTS OTHER'],
		'lowvisionsales' => ['RX SAFETY'],
		'dispensingsales' => ['LIQUID']

	];

	// Order Status Values
	const PENDING_STATUS            = 'PENDING'; // standard status, order is "pending" export to M3
	const PENDING_WEB_STATUS        = 'PENDING_WEB'; // status signifying order needs microsite approval
    const DENIED_STATUS             = 'DENIED'; // status signifying the microsite approver rejected the order
	const PENDING_APPROVAL_STATUS   = 'PENDING_APPROVAL'; // status signifying order needs approval by a CSR in CST

	const B2B_ORDER_ORIGIN          = 'B2B';
	const CST_ORDER_ORIGIN          = 'CST';
	const LEGACY_ORDER_ORIGIN       = 'HISTORY';
	const M3_ORDER_ORIGIN           = 'M3';
    const VISIONWEB_ORDER_ORIGIN    = 'VISIONWEB';

    use SoftDeletes;

    public function import_SalesOrder(){
        return $this->hasOne(Import_SalesOrder::class, 'salesorder_id');
    }
    
    public function authorization(){
        return $this->hasOne(CreditCardAuthorization::class, 'salesorder_id');
    }

    public function webSilo() {
        return $this->belongsTo(WebSilo::class, "websilo_id");
    }

	public function fob() {
		return $this->belongsTo(FOB::class, "fob_id");
	}

	public function salesrep() {
		return $this->belongsTo(SalesRep::class, "salesrep_id");
	}

	public function orderedByUser() {
	    return $this->belongsTo(WebUser::class, 'webuser_id', 'id');
    }

    public function approvedByUser() {
        return $this->belongsTo(WebUser::class, 'approver_webuser_id', 'id');
    }

	public function salesOrderSource() {
		return $this->belongsTo(SalesOrderSource::class, "salesordersource_id");
	}

	public function orderLineSchedules()
	{
		return $this->hasMany(SalesOrderLineSchedule::class, 'salesorder_id');
	}

	public function carrier() {
		return $this->belongsTo(Carrier::class, "carrier_id");
	}

	public function deliveryMethodTerm(){
	    return DeliveryMethodTerm::delivery($this->deliverymethod_id, $this->deliveryterm_id, $this->delivery_priority);
    }

	public function deliveryMethod(){
	    return $this->belongsTo(DeliveryMethod::class, "deliverymethod_id");
    }

    public function deliveryTerm(){
	    return $this->belongsTo(DeliveryTerm::class, "deliveryterm_id");
    }
	
	public function division() {
		return $this->belongsTo(Division::class, "division_id");
	}

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

	public function paymentTerms() {
	    return $this->belongsTo(PaymentTerm::class, 'paymentterm_id', 'id');
    }

//	public function mainLines()
//	{
//		return $this->hasMany(OrderMainLine::class, 'salesorder_id')
//			->join('SalesOrderPartLines', 'SalesOrderMainLines.parent_id', '=', 'SalesOrderPartLines.id')
//			->join('Parts', 'SalesOrderPartLines.part_id', '=', 'Parts.id')
//			->join('ProductFamily', 'Parts.productfamily_id', '=', 'ProductFamily.id')
//			->join('ProductCategories', 'ProductFamily.productcategory_id', '=', 'ProductCategories.id')
//			->join('ProductCategoryGroups', 'ProductCategories.productcategorygroup_id', '=', 'ProductCategoryGroups.id')
//			->where('SalesOrderMainLines.deleted_at', '=', "0")
////			->groupBy('ProductCategories.product_category')
////			->addSelect('SalesOrderMainLines.*', 'ProductCategories.product_category','ProductCategoryGroups.product_category_group')
////			->addSelect(DB::raw('SUM(SalesOrders.order_amount) as category_total'))
//			;
//	}

	public function partLines() {
	    return $this->hasMany(SalesOrderLine::class, 'salesorder_id')->where('deleted_at', '=', '0000-00-00')->with('part');
//		return $this->hasMany(OrderMainLine::class, 'salesorder_id')->where('parent_type', 'SalesOrderPartLines')->where('deleted_at', '=', '0000-00-00')->with('partLines.part');
	}

	public function miscLines() {
		return $this->hasMany(OrderMainLine::class, 'salesorder_id')->where('parent_type', 'SalesOrderMiscLines')->where('deleted_at', '=', '0000-00-00')->with('miscLines.miscCharge');
	}
	
	public function soldToCustomer() {
		return $this->belongsTo(Customer::class, "soldto_customer_id");
	}

	public function billToCustomer() {
		return $this->belongsTo(Customer::class, "billto_customer_id");
	}

	public function billToCustomerSegment() {
	    $activeSegments = $this->billToCustomer->activeSegments;
	    if ($activeSegments) {
	        return $activeSegments->take(1);
        } else {
	        return null;
        }
    }

    public function shipToAddress() {
        return $this->belongsTo(CustomerShippingAddress::class, "customershippingaddress_id");
    }

    public function shipToAddressWithTrashed() {
	    return $this->belongsTo(CustomerShippingAddress::class, "customershippingaddress_id")->withTrashed();
    }

	public function orderShipPlant() {
		return $this->belongsTo(Plant::class, 'plant_id');
	}

	public function orderShipWarehouse() {
		return $this->belongsTo(Warehouse::class, 'warehouse_id');
	}

	public function orderShipBinLocation() {
		return $this->belongsTo(BinLocation::class, 'binlocation_id');
	}

	public function creditCardAuthorization() {
	    return $this->hasMany(CreditCardAuthorization::class, 'salesorder_id');
    }

    public function cstEnteredPharmacyInfo() {
	    return $this->hasOne(CSTEnteredPharmacyInfo::class, 'salesorder_id');
    }
	
	public function comments() {

		$comments = [];
		if ($this->comment_all != null && $this->comment_all != '') {
			$comments['A'] = $this->comment_all;
		}
		if ($this->comment_external != null && $this->comment_external != '') {
			$comments['E'] = $this->comment_external;
		}
		if ($this->comment_internal != null && $this->comment_internal != '') {
			$comments['I'] = $this->comment_internal;
		}
		if ($this->comment_display != null && $this->comment_display != '') {
			$comments['D'] = $this->comment_display;
		}

		return $comments;
	}

	public function orderParts()
	{
        $orderParts = $this->hasMany(SalesOrderLine::class, 'salesorder_id')
            ->join('Parts', 'SalesOrderLines.part_id', '=', 'Parts.id');

		return $orderParts;
	}

	public function scopeSubmitted($query) {
	    return $query->whereNotIn('order_status', ['UNSUBMITTED', 'DISCARDED', 'CANCELED', 'CANCELLED']);
    }

	public function scopeLastOrders($query, $soldToCustomerId, $take) {
	    return $query
            ->where('soldto_customer_id', $soldToCustomerId)
            ->orderBy('order_date', 'desc')
            ->with('orderParts')
            ->take($take);
    }

    public function scopeDateBetween($query, $fromDate, $toDate = false) {
        if ($toDate === false) {
            $query->where('order_date', '>=', $fromDate);
        } else {
            $query->whereBetween('order_date', [$fromDate, $toDate]);
        }
        return $query;
    }

    public function getFriendlyOrderStatusAttribute() {
        return $this->friendlyStatus($this->order_status);
    }

    public static function friendlyStatus($status) {
        switch ($status) {
            case 'CLOSED':
                return 'Closed';
            case 'PENDING_WEB':
                return 'Pending Approval';
            case 'DENIED':
                return 'Approval Denied';
        }

        return 'Open';
    }

    public function getTotalQuantityAttribute() {
        $qty = 0;
        $partLines = $this->partLines;
        if ($partLines) {
            foreach($partLines as $partLine){
                $qty += $partLine->quantity;
            }
        }

        return $qty;
    }

    public function getTotalShippedAttribute() {
        $qtyShipped = 0;
        if (isset($this->import_SalesOrder)) {
            foreach ($this->import_SalesOrder->shipmentUnitItems as $shipmentUnitItem) {
                $qtyShipped += $shipmentUnitItem->qty_shipped;
            }
        }
        return $qtyShipped;
    }

    public function getTrackingNumbersAttribute() {
        $numbers = [];
        foreach ($this->orderLineSchedules as $lineSchedule) {
            $numbers[$lineSchedule->shipment->tracking_number] = $lineSchedule->shipment->tracking_number;
        }
        return $numbers;
    }

    public function scopeToday($query) {
//        return $query->whereBetween('date_created', [Carbon::today()->startOfDay()->toDateTimeString(), Carbon::today()->endOfDay()->toDateTimeString()]);
        return $query->where('order_date', Carbon::today()->toDateString());
    }

    public function scopeWebOrders($query) {
        return $query->where('order_origin', 'B2B');
    }

    public function scopeCstOrders($query) {
        return $query->where('hilco_order_number', 'RLIKE', '^[HUW]')->where(function ($where) {
            $where->whereNull('order_origin')->orWhere('order_origin', '!=', 'B2B');
        });
    }

    public function getApprovedAttribute() {
	    return (bool) !($this->order_status == 'PENDING_WEB' || $this->order_status == 'DENIED');
    }

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

    public function priceListSalesOrder() {
	    return $this->hasOne(PriceList_SalesOrder::class, 'salesorder_id');
    }

    public function approvalReasonSalesOrder() {
        return $this->hasOne(ApprovalReasonSalesOrder::class, 'salesorder_id', 'id');
    }
}