<?php

namespace Modules\Mall\Models\Traits;

use App\Notifications\SystemOrderDelivered;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Modules\Mall\Events\OrderCanceled;
use Modules\Mall\Events\OrderCompleted;
use Modules\Mall\Events\OrderDelivered;
use Modules\Mall\Events\OrderPaid;
use Modules\Mall\Events\OrderSigned;
use Modules\Mall\Models\Order;

trait OrderActions
{

    /**
     * Notes   : 订单取消
     *
     * @Date   : 2021/5/17 10:36 上午
     * @Author : < Jason.C >
     * @throws \Exception
     */
    public function cancel(): bool
    {
        if ($this->canCancel()) {
            // 修改状态机
            $this->apply('cancel');

            event(new OrderCanceled($this));

            return true;
        } else {
            throw new \Exception('订单状态不可取消');
        }
    }

    /**
     * 订单支付
     *
     * @throws \Exception
     */
    public function pay(): bool
    {
        if ($this->can('pay')) {
            // 修改状态机
            $this->paid_at = Carbon::now();
            $this->apply('pay');

            event(new OrderPaid($this));

            //增加记录
            $this->addTimeline();

            return true;
        } else {
            throw new \Exception('订单状态不可支付');
        }
    }

    /**
     * Notes   : 订单发货
     *
     * @Date   : 2021/5/14 16:45
     * @Author : Mr.wang
     * @param  int  $expressId  物流公司ID
     * @param  string  $expressNo  物流单号
     * @return bool
     * @throws \Exception
     */
    public function deliver($expressId, $expressNo, $type = 1, $person = ''): bool
    {
        if ($this->can('deliver')) {
            if ($this->refund_items_count == $this->items()->count()) {
                throw new \Exception('商品已全部退款/货不能发货');
            }

            DB::transaction(function () use ($expressId, $expressNo, $type, $person) {
                $this->express()->update([
                    'express_id' => $expressId ?? null,
                    'express_no' => $expressNo ?? null,
                    'type'       => $type,
                    'person'     => $person,
                    'deliver_at' => now(),
                ]);
                // 修改状态机
                $this->apply('deliver');

                event(new OrderDelivered($this));

                if ($this->type == Order::TYPE_SAMPLE) {
                    $this->user->notify(new SystemOrderDelivered('发货提醒', $this));
                }

            });

            return true;
        } else {
            throw new \Exception('订单状态不可发货');
        }
    }

    /**
     * Notes   : 订单签收
     *
     * @Date   : 2021/5/14 17:09
     * @Author : Mr.wang
     * @return bool
     * @throws \Exception
     */
    public function sign(): bool
    {
        if ($this->can('sign')) {
            DB::transaction(function () {
                $this->express()->update([
                    'receive_at' => now(),
                ]);
                // 修改状态机
                $this->apply('sign');
            });
            event(new OrderSigned($this));

            return true;
        } else {
            throw new \Exception('订单状态不可签收');
        }
    }

    /**
     * Notes   : 订单完成
     *
     * @Date   : 2021/5/21 2:57 下午
     * @Author : < Jason.C >
     * @return bool
     * @throws \Exception
     */
    public function complete(): bool
    {
        if ($this->can('complete')) {
            // 修改状态机
            $this->apply('complete');

            event(new OrderCompleted($this));

            return true;
        } else {
            throw new \Exception('订单状态不可完成');
        }
    }

    /**
     * Notes: 设置退款
     *
     * @Author: 玄尘
     * @Date  : 2021/6/9 9:53
     */
    public function refund()
    {
        if ($this->can('refund')) {
            // 修改状态机
            $this->apply('refund');

            return true;
        } else {
            throw new \Exception('订单状态不可设置退款');
        }
    }

    /**
     * Notes: 退款完成
     *
     * @Author: 玄尘
     * @Date  : 2021/6/9 12:00
     */
    public function completed()
    {
        if ($this->can('completed')) {
            // 修改状态机
            $this->apply('completed');

            return true;
        } else {
            throw new \Exception('订单状态不可设置退款完成');
        }
    }

}
