<?php

namespace app\common\model;

use think\Model;
use think\Db;

class Order extends Model
{
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';
    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';

    protected $append = [
        'type',
    ];

    // 错误提示
    public $error = '';

    /**
     * 订单商品列表
     */
    public function goods()
    {
        return $this->hasMany('OrderGoods');
    }

    /**
     * 关联订单收货地址表
     */
    public function address()
    {
        return $this->hasOne('OrderAddress');
    }

    /**
     * 关联售后表
     */
    public function refund()
    {
        return $this->hasOne('OrderRefund');
    }

    /**
     * 订单状态
     */
    public function getTypeAttr($value,$data){
        $type = ['name'=>'待支付','value'=>'payment'];
        if($data['refund_status'] > '0'){
            if($this['refund']['type'] == '1'){
                $refund_status_arr = ['1'=>'退款申请中','2'=>'已退款','3'=>'已拒绝'];
                $type = [
                    'name' => $refund_status_arr[$data['refund_status']],
                    'value' => 'refund_'.$data['refund_status']
                ];
            }else{
                $refund_status_arr = ['1'=>'退货申请中','2'=>'已退款','3'=>'已拒绝'];
                $type = [
                    'name' => $refund_status_arr[$data['refund_status']],
                    'value' => 'return_goods_'.$data['refund_status']
                ];
            }
        }else{
            if($data['pay_status'] == '0'){
                $type = [
                    'name' => '待支付',
                    'value' => 'payment'
                ];
            }else{
                if($data['delivery_status'] == '0'){
                    $type = [
                        'name' => '待发货',
                        'value' => 'delivery'
                    ];
                }else{
                    if($data['receive_status'] == '0'){
                        $type = [
                            'name' => '待收货',
                            'value' => 'receive'
                        ];
                    }else{
                        if($data['appraise_status'] == '0'){
                            $type = [
                                'name' => '待评价',
                                'value' => 'appraise'
                            ];
                        }else{
                            $type = [
                                'name' => '已完成',
                                'value' => 'completed'
                            ];
                        }
                    }
                }
            }
        }
        return $type;
    }

    /**
     * 新增订单
     */
    public function add($user_id, $order)
    {
        if (empty($order['address'])) {
            $this->error = '请先选择收货地址';
            return false;
        }
        Db::startTrans();
        // 记录订单信息
        $this->save([
            'user_id' => $user_id,
            'order_no' => date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8),
            'total_price' => $order['total_price'],
            'order_price' => $order['order_price'],
            'express_price' => $order['express_price'],
            'reduce_price' => $order['reduce_price'],
            'user_coupon_id' => $order['coupon']['user_coupon_id'],
            'coupon_price' => $order['coupon']['coupon_price'],
            'score' => $order['score']['score_price'] > 0 ? $order['score']['use_score'] : 0,
            'score_price' => $order['score']['score_price']
        ]);
        // 订单商品列表
        $goodsList = [];
        foreach ($order['goods_list'] as $goods) {
            $goodsList[] = [
                'goods_id' => $goods['goods_id'],
                'goods_name' => $goods['goods']['goods_name'],
                'goods_image' => $goods['goods']['goods_image'],
                'goods_price' => $goods['goods_price'],
                'goods_num' => $goods['goods_num'],
                'user_size_id' => !empty($goods['user_size']) ? $goods['user_size']['id'] : 0,
                'make_type' => $goods['make_type'],
                'goods_style' => $goods['goods_style'],
                'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
                'goods_attr' => $goods['goods_sku']['goods_attr'],
                'goods_total_price' => $goods['goods_total_price']
            ];
        }
        // 保存订单商品信息
        $this->goods()->saveAll($goodsList);
        // 记录收货地址
        $this->address()->save([
            'user_address_id' => $order['address']['id'],
            'name' => $order['address']['name'],
            'phone' => $order['address']['phone'],
            'province_id' => $order['address']['province_id'],
            'city_id' => $order['address']['city_id'],
            'district_id' => $order['address']['district_id'],
            'detail' => $order['address']['detail'],
        ]);
        // 用掉优惠券
        if($order['coupon']['user_coupon_id'] > 0){
            UserCoupon::where('id',$order['coupon']['user_coupon_id'])->setField('status','2');
        }
        // 用掉积分
        if($order['score']['use_score'] > 0){
            User::score(-$order['score']['use_score'],$user_id,'订单支付-使用积分');
        }
        Db::commit();
        return true;
    }

    /**
     * 用户中心订单列表
     */
    public function getList($user_id, $type = 'all')
    {
        // 筛选条件
        $filter = [];
        // 排序方式
        $order = ['createtime' => 'desc'];
        // 订单数据类型
        switch ($type) {
            case 'all':
                break;
            case 'payment';//待支付
                $filter['pay_status'] = '0';
                $filter['refund_status'] = '0';
                $order = ['createtime' => 'asc'];
                break;
            case 'delivery';//待发货
                $filter['pay_status'] = '1';
                $filter['delivery_status'] = '0';
                $filter['refund_status'] = '0';
                break;
            case 'receive';//待收货
                $filter['pay_status'] = '1';
                $filter['delivery_status'] = '1';
                $filter['receive_status'] = '0';
                $filter['refund_status'] = '0';
                break;
            case 'appraise';//待评价
                $filter['pay_status'] = '1';
                $filter['delivery_status'] = '1';
                $filter['receive_status'] = '1';
                $filter['appraise_status'] = '0';
                $filter['refund_status'] = '0';
                break;
        }
        return $this->with(['goods'=>['user_size'],'address'])
            ->where('user_id', $user_id)
            ->where('order_status', '<>', '2')
            ->where($filter)
            ->order($order)
            ->select();
    }

    /**
     * 订单详情
     */
    public function getUserOrderDetail($order_id, $user_id)
    {
        if (!$order = $this->get([
            'id' => $order_id,
            'user_id' => $user_id,
            'order_status' => ['<>', '2']
        ], ['goods' => ['goods','user_size','spec'], 'address', 'refund'])) {
            $this->setError('订单不存在');
            return false;
        }
        return $order;
    }

    /**
     * 取消订单
     */
    public function cancel()
    {
        if ($this['pay_status'] == '1') {
            $this->setError('已付款订单不可取消');
            return false;
        }
        // 退回优惠券
        if($this['user_coupon_id'] > 0){
            UserCoupon::where('id',$this['user_coupon_id'])->setField('status','1');
        }
        // 退回积分
        if($this['score'] > 0){
            User::score(-$this['score'],$this['user_id'],'取消订单,退回积分');
        }
        return $this->save(['order_status' => '2']);
    }

    /**
     * 提醒发货
     */
    public function remind()
    {
        if ($this['delivery_status'] == '1') {
            $this->setError('订单已发货');
            return false;
        }
        if(cache('remind_'.$this['id'])){
            $this->setError('您已提醒发货,请稍后再提醒');
            return false;
        }
        cache('remind_'.$this['id'],$this['id'],60);
        return true;
    }

    /**
     * 查询物流
     */
    public function orderTraces()
    {
        if ($this['delivery_status'] == '0') {
            $this->setError('该订单不合法');
            return false;
        }
        $kdniao = new \addons\kdniao\library\Kdniao();
        $wuliu = $kdniao->getOrderTracesByJson($this['express_code'], $this['express_no']);
        if($wuliu == -1){
            $this->setError('未设置接口配置!请在插件管理中配置!');
            return false;
        }
        $wuliu = json_decode($wuliu, true);
        return isset($wuliu['Traces']) && count($wuliu['Traces']) ? array_reverse($wuliu['Traces']) : [['AcceptStation' => '暂无物流信息', 'AcceptTime' => date('Y-m-d H:i:s', time())]];
    }

    /**
     * 申请退款
     */
    public function toRefund($post)
    {
        if($this['pay_status'] == '0'){
            $this->setError('未支付非法订单!');
            return false;
        }
        if(empty($post['reason'])){
            $this->setError('请选择退款原因!');
            return false;
        }
        if($this['refund_status'] == '2'){
            $this->setError('订单已退款!');
            return false;
        }
        if($this['refund_status'] == '1'){
            $this->setError('正在申请退款中!');
            return false;
        }
        if($this['delivery_status'] == '1'){
            $this->setError('订单当前无法退款!');
            return false;
        }
        Db::startTrans();
        if(!$this['refund']){
            $this->refund()->save(array_merge([
                'type' => '1'
            ],$post));
        }else{
            $this['refund']->save($post);
        }
        $this->save(['refund_status'=>'1']);
        Db::commit();
        return true;
    }

    /**
     * 申请退货
     */
    public function returnGoods($post)
    {
        if(empty($post['reason'])){
            $this->setError('请选择退货原因!');
            return false;
        }
        if($this['refund_status'] == '2'){
            $this->setError('订单已退货!');
            return false;
        }
        if($this['refund_status'] == '1'){
            $this->setError('正在申请退货中!');
            return false;
        }
        if($this['receive_status'] == '1'){
            $this->setError('订单当前无法退货!');
            return false;
        }
        Db::startTrans();
        if(!$this['refund']){
            $this->refund()->save(array_merge([
                'type' => '2'
            ],$post));
        }else{
            $this['refund']->save($post);
        }
        $this->save(['refund_status'=>'1']);
        Db::commit();
        return true;
    }

    /**
     * 确认收货
     */
    public function receive()
    {
        if ($this['delivery_status'] == '0' || $this['receive_status'] == '1') {
            $this->setError('该订单不合法');
            return false;
        }
        return $this->save([
            'receive_status' => '1',
            'receive_time' => time(),
            'order_status' => '3'
        ]);
    }

    /**
     * 判断商品库存不足 (未付款订单)
     */
    public function checkGoodsStatusFromOrder($goodsList)
    {
        foreach ($goodsList as $order_goods) {
            $goods = Goods::get($order_goods['goods_id'],['spec_rel.spec']);
            // 判断商品是否下架
            if ($goods['issale'] != '1') {
                $this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 已下架');
                return false;
            }
            // 付款减库存
            if ($goods['ismake'] == '0' && $goods->getGoodsSku($order_goods['spec_sku_id'])['stock_num'] < 1) {
                $this->setError('很抱歉,商品 [' . $goods['goods_name'] . '] 库存不足');
                return false;
            }
        }
        return true;
    }

    /**
     * 待支付订单时效为24小时,超时将成为无效订单,系统自动将订单从待付款页面移出。
     */
    public function checkPaymentOrder($user_id)
    {
        $list = $this->getList($user_id,'payment');
        foreach($list as $v){
            $v->cancel();
        }
        return true;
    }

    /**
     * 设置错误信息
     * @param $error
     */
    private function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }

    /**
     * 是否存在错误
     * @return bool
     */
    private function hasError()
    {
        return !empty($this->error);
    }

    /**
     * 获取错误信息
     * @return string
     */
    public function getError()
    {
        return $this->error;
    }
}