<?php
namespace Modules\Project\Services\Order;

use Modules\Project\Events\OrderCompleteEvent;
use Modules\Project\Events\OrderPaymentSuccessEvent;
use Modules\Project\Entities\Order;
use Modules\Project\Services\GoodsService;

class ChangeStatus
{
    public $is_order_save = true;
    public $is_order_log_save = true;
    public $is_order_event = true;
    public $order;
    public $after_status = null;
    public $before_status;
    public $save_data = [];
    public $save_log_data = [];
    public $before_order_data = [];

    public function __construct(Order $order)
    {
        $this->order = $order;
        $this->before_status = $this->order->status;
        $this->before_order_data = $this->order->toArray();
    }

    public function changeStatus($data = [])
    {
        if ($this->after_status === null) {
            throw new \Exception('after status 不能为空');
        }

        $after_status = $this->after_status;

        return $this->callStatus($after_status, $data);
    }

    protected function callStatus($status, $param = [])
    {
        $name = $this->statusToName($status);
        if ($this->is_order_save) {
            $this->existsOrCall("order{$name}Save", 'orderSave', $param);
        }
        if ($this->is_order_log_save) {
            $this->existsOrCall("order{$name}LogSave", 'orderLogSave', $param);
        }
        if ($this->is_order_event) {
            $this->existsOrCall("order{$name}Event", 'orderEvent', $param);
        }
    }

    protected function statusToName($status)
    {
        switch ($status) {
            case Order::STATUS_CANCEL:
                return 'Cancel';
                break;
            case Order::STATUS_PAID:
                return 'Paid';
                break;
            case Order::STATUS_SHIPPED:
                return 'Shipped';
                break;
            case Order::STATUS_CONFIRM:
                return 'Confirm';
                break;
            case Order::STATUS_COMPLETE:
                return 'Complete';
                break;
        }

        return '';
    }

    protected function existsOrCall($method_name, $func, $param = [])
    {
        if (method_exists($this, $method_name)) {
            call_user_func([$this,$method_name], ...$param);
        } else {
            call_user_func([$this,$func], ...$param);
        }
    }

    protected function orderSave()
    {
        $data = $this->save_data;
        $data['status'] = $this->after_status;
        $this->order->update($data);
    }

    protected function orderLogSave()
    {
        $data = $this->save_log_data;
        $data['after_status'] = $this->after_status;
        $data['before_status'] = $this->before_status;
        $this->order->addLog($data);
    }

    protected function orderEvent()
    {
        //dump('orderEvent');
    }

    /**
     * 取消订单
     */
    protected function orderCancelSave()
    {
        $data = $this->save_data;
        $data['status'] = $this->after_status;
        $this->order->update($data);
    }

    /**
     * 取消订单
     */
    protected function orderCancelEvent()
    {
        $this->revoke();
    }

    /**
     * 支付成功
     */
    protected function orderPaidEvent()
    {
        event(new OrderPaymentSuccessEvent($this->order));
    }

    /**
     * 完成订单
     */
    protected function orderCompleteEvent()
    {
        event(new OrderCompleteEvent($this->order));
    }

    /**
     * 订单发货
     */
    protected function orderShippedSave()
    {
        $data = $this->save_data;
        $data['status'] = $this->after_status;
        $data['shipped_at'] = isset($data['shipped_at']) ? $data['shipped_at'] : date('Y-m-d H:i:s');
        $this->order->update($data);
    }

    /**
     * 确认订单
     */
    protected function orderConfirmEvent()
    {
        $this->orderCompleteEvent();
    }

    /**
     * 返回库存
     */
    protected function revoke()
    {
        $this->order->orderGoods->each(function ($order_goods) {
            GoodsService::stockpiling($order_goods->goods->id, json_decode($order_goods->spec, true), $order_goods->qty);
        });
    }
}
