<?php
/**
 * Created by PhpStorm.
 * User: steven
 * Date: 7/30/19
 * Time: 4:27 PM
 */

namespace Hilco\Models;

use Arr;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Query\Builder;
use Throwable;

/**
 * @property mixed $id
 * @property mixed $division_id
 * @property mixed $salesorder_id
 * @property int $line_number
 * @property mixed $line_status
 * @property mixed $plant_id
 * @property mixed $warehouse_id
 * @property mixed $binlocation_id
 * @property bool $nocharge_flag
 * @property int $part_id
 * @property int $quantity
 * @property float $unit_price
 * @property bool $taxable
 * @property string $date_created
 * @property string $date_modified
 * @property string $date_uploaded
 * @property string $deleted_at
 * @property bool $is_kit
 * @property float $override_price
 * @property string $pricelist
 * @property int $is_contract
 * @property string $customer_reference
 * @property float $ext_tax
 * @property-read mixed $id_string
 * @method static Builder|OrderMainLine whereId($value)
 * @method static Builder|OrderMainLine whereDivisionId($value)
 * @method static Builder|OrderMainLine wherePlantId($value)
 * @method static Builder|OrderMainLine whereInvoiceNumber($value)
 * @method static Builder|OrderMainLine whereBilltoCustomersegmentId($value)
 * @method static Builder|OrderMainLine whereSoldtoCustomersegmentId($value)
 * @method static Builder|OrderMainLine whereFob($value)
 * @method static Builder|OrderMainLine wherePaymentTerms($value)
 * @method static Builder|OrderMainLine whereTaxAmt($value)
 * @method static Builder|OrderMainLine whereFreightAmt($value)
 * @method static Builder|OrderMainLine whereInvoiceDate($value)
 * @method static Builder|OrderMainLine whereShipDate($value)
 * @method static Builder|OrderMainLine whereCarrier($value)
 * @method static Builder|OrderMainLine whereShipVia($value)
 * @method static Builder|OrderMainLine whereCustomerPo($value)
 * @method static Builder|OrderMainLine whereShippingPolicy($value)
 * @method static Builder|OrderMainLine whereDateCreated($value)
 * @method static Builder|OrderMainLine whereDateModified($value)
 * @method static Builder|OrderMainLine whereDeletedAt($value)
 * @mixin \Eloquent
 * @property Part part
 * @property-read OrderPartLine $partLines
 * @property-read Collection|OrderDiscountLine[] $discLines
 * @method static Builder|OrderMainLine whereParentId($value)
 * @method static Builder|OrderMainLine whereParentType($value)
 * @method static Builder|OrderMainLine whereSalesorderId($value)
 * @method static Builder|OrderMainLine whereLineNumber($value)
 * @method static Builder|OrderMainLine whereLineStatus($value)
 * @method static Builder|OrderMainLine whereWarehouseId($value)
 * @method static Builder|OrderMainLine whereBinlocationId($value)
 * @method static Builder|OrderMainLine whereDateUploaded($value)
 * @method static Builder|OrderMainLine whereLineOrder($value)
 * @method static Builder|OrderMainLine whereLineSuborder($value)
 */
class SalesOrderLine extends UuidModel {
    protected $table = 'SalesOrderLines';
    protected $fillable = [
        'id', 'division_id', 'salesorder_id',
        'line_number', 'line_status',
        'plant_id', 'nocharge_flag', 'part_id', 'quantity',
        'unit_price', 'taxable', 'is_kit', 'override_price',
        'pricelist', 'is_contract', 'customer_reference',
        'line_comment_all', 'line_comment_deliverynote', 'line_comment_display', 'line_comment_external',
        'line_comment_internal', 'line_comment_invoice', 'line_comment_manufacturing', 'line_comment_picklist',
        'uom', 'ext_tax',
        'commit_sequence',
    ];

    const OPEN_STATUS = "OPEN";

    /**
     * @param StagedOrderLine $stagedOrderLine
     * @param int $commit_sequence
     * @return SalesOrderLine
     * @throws Throwable
     */
    public static function createFromStaged (StagedOrderLine $stagedOrderLine, int $commit_sequence): SalesOrderLine {
        $stagedOrder = $stagedOrderLine->stagedOrder;
        $salesOrder = $stagedOrder->salesOrder;
        $salesOrderLine = new SalesOrderLine([
            'id' => generateUUID(),
            'division_id' => $stagedOrder->division_id,
            'salesorder_id' => $salesOrder->id,
            'line_number' => $stagedOrderLine->getLineNumber(),
            'line_status' => SalesOrderLine::OPEN_STATUS,
            'plant_id' => $stagedOrderLine->plant_id,
            'nocharge_flag' => $stagedOrderLine->nocharge_flag,
            'part_id' => $stagedOrderLine->part_id,
            'quantity' => $stagedOrderLine->getQuantity(),
            'unit_price' => $stagedOrderLine->getUnitPriceNumeric(),
            'taxable' => $stagedOrderLine->taxable,
            'is_kit' => $stagedOrderLine->is_kit,
            'override_price' => $stagedOrderLine->getOverridePrice(),
            'pricelist' => $stagedOrderLine->getPriceList(),
            'is_contract' => $stagedOrderLine->is_contract,
            'customer_reference' => $stagedOrderLine->getCustomerReference(),
            'line_comment_all' => $stagedOrderLine->getComment("all"),
            'line_comment_deliverynote' => $stagedOrderLine->getComment("deliverynote"),
            'line_comment_display' => $stagedOrderLine->getComment("display"),
            'line_comment_external' => $stagedOrderLine->getComment("external"),
            'line_comment_internal' => $stagedOrderLine->getComment("internal"),
            'line_comment_invoice' => $stagedOrderLine->getComment("invoice"),
            'line_comment_manufacturing' => $stagedOrderLine->getComment("manufacturing"),
            'line_comment_picklist' => $stagedOrderLine->getComment("picklist"),
            'uom' => $stagedOrderLine->part->getUOM(),
            'ext_tax' => $stagedOrderLine->ext_tax,
            'commit_sequence' => $commit_sequence,
        ]);
        $salesOrderLine->saveOrFail();
        return $salesOrderLine;
    }
    public function salesOrderStatus() {
        return $this->hasMany(SalesOrderStatus::class, 'salesordermainline_id', 'id');
    }

    public function miscLine()
    {
        return $this->hasOne(OrderMiscLine::class, 'id', 'parent_id')->with('miscCharge');
    }

    public function subLines()
    {
        return $this->hasMany(OrderSubLine::class, 'salesordermainline_id')->where('parent_type', 'SalesOrderDiscLines');
    }

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

    public function discLines(){
        return $this->hasMany(OrderDiscountLine::class, 'salesorderline_id')->whereNull('deleted_at');
    }

    public function miscSubLines()
    {
        return $this->hasMany(OrderSubLine::class, 'salesordermainline_id')->where('parent_type', 'SalesOrderMiscLines')->whereNull('deleted_at')->with('miscLine.miscCharge');
    }

    public function miscLines(){
        return $this->hasMany(OrderMiscLine::class, 'salesorderline_id')->where('deleted_at', '=', '0000-00-00 00:00:00')->with('miscCharge');
    }

    public function attnSubLine() {
        return $this->hasOne(OrderSubLine::class, 'salesordermainline_id')->where('parent_type', 'SalesOrderAttnLines')->with('attnLine');
    }

    public function instructionSubLine() {
        return $this->hasOne(OrderSubLine::class, 'salesordermainline_id')->where('parent_type', 'SalesOrderInstructionLines')->with('instructionLine');
    }

    public function xrefSubLine() {
        return $this->hasOne(OrderSubLine::class, 'salesordermainline_id')->where('parent_type', 'SalesOrderXrefLines')->with('xrefLine');
    }

    public function commentLine()
    {
        return $this->hasOne(OrderSubLine::class, 'salesordermainline_id')->where('parent_type', 'SalesOrderCommentLines')->with('commentLine');
    }

    public function extractComments($subLine) {
        if (is_null($subLine)) return [];
        $commentLine = $subLine->commentLine;
        $comments = [];
        if ($commentLine->line_comment_all != null && $commentLine->line_comment_all != '') {
            $comments['A'] = $commentLine->line_comment_all;
        }
        if ($commentLine->line_comment_external != null && $commentLine->line_comment_external != '') {
            $comments['E'] = $commentLine->line_comment_external;
        }
        if ($commentLine->line_comment_internal != null && $commentLine->line_comment_internal != '') {
            $comments['I'] = $commentLine->line_comment_internal;
        }
        if ($commentLine->line_comment_display != null && $commentLine->line_comment_display!= '') {
            $comments['D'] = $commentLine->line_comment_display;
        }
        return $comments;
    }

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

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

    public function order() {
        return $this->belongsTo(Order::class, 'salesorder_id');
    }

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

    public function getTotalDiscount() {
        $totalDiscount = 0;
        foreach ($this->discLines as $discLine) {
            $totalDiscount += $discLine->discount_amount;
        }
        return $totalDiscount;
    }

    public function getDiscountUnitPriceExtension() {
        return ($this->unit_price - $this->getTotalDiscount()) * $this->quantity;
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function part() {
        return $this->belongsTo(Part::class, 'part_id');
    }

    // Do we have any use for this?

    public function priceLists() {
        return $this->hasMany(PriceList::class, 'part_id', 'part_id');
    }

    public function getPriceListPriceAttribute() {
        $priceLists = $this->priceLists->sortByDesc('quantity_level');
        foreach ($priceLists as $priceList) {
            if ($this->quantity >= $priceList->quantity_level) {
                return $priceList->price;
            }
        }
        return null;
    }

    public function getLineCustomerDiscountPrice(){
        $price = $this->unit_price * $this->quantity;
        $discounts = OrderDiscountLine::where('salesorderline_id', '=', $this->id)->get();
        foreach($discounts as $discount){
            if($discount->discount_code === 'Rewards' || $discount->discount_code === 'REWARDS'){
                if($discount->discount_amount > 0){
                    $price -= $discount->discount_amount;
                    break;
                }
            }
        }

        return $price;
    }

    public function getHubSpotEventProperties ($webHierarchyId): array {
        $part = $this->part;
        $webPart = $part->webPart;
        $webFamily = null;
        if (isset($webPart) && isset($webHierarchyId)) {
            $webFamily = $webPart->webFamilyInHierarchy($webHierarchyId)->first();
        }
        return [
            'item_1_image_url'          => WebAsset::urlHelper([
                'key' => Arr::get($part, 'part_no', ''),
                'prefix' => 'pn',
            ]),
            'item_1_name'               => $part->part_desc,
            'item_1_price'              => $this->unit_price,
            'item_1_product_id'         => $part->part_no,
            'item_1_product_url'        => config('hubspot.product_url_prefix').'f/'.Arr::get($webFamily, 'slug', '').'/'.Arr::get($webPart, 'id', ''),
            'item_1_quantity'           => $this->quantity,
            'item_1_row_total'          => $this->quantity * $this->unit_price,
            'item_1_small_image_url'    => WebAsset::urlHelper([
                'key' => Arr::get($part, 'part_no', ''),
                'prefix' => 'pn',
                'width' => 150,
                'height' => 150
            ]),
        ];
    }

}