<?php

namespace app\api\logic;

use app\common\basics\Logic;
use app\common\enum\ClientEnum;
use app\common\enum\FootprintEnum;
use app\common\enum\GoodsEnum;
use app\common\enum\OrderEnum;
use app\common\enum\OrderGoodsEnum;
use app\common\enum\OrderInvoiceEnum;
use app\common\enum\OrderLogEnum;
use app\common\enum\PayEnum;
use app\common\enum\ShopEnum;
use app\common\enum\TeamEnum;
use app\common\logic\OrderLogLogic;
use app\common\logic\OrderRefundLogic;
use app\common\model\Cart;
use app\common\model\Freight;
use app\common\model\goods\Goods;
use app\common\model\Delivery;
use app\common\model\goods\GoodsItem;
use app\common\model\integral\IntegralOrder;
use app\common\model\order\Order;
use app\common\model\order\OrderGoods;
use app\common\model\order\OrderLog;
use app\common\model\order\OrderRefund;
use app\common\model\order\OrderTrade;
use app\common\model\Pay;
use app\common\model\RechargeOrder;
use app\common\model\shop\Shop;
use app\common\model\coupon\Coupon;
use app\common\model\coupon\CouponList;
use app\common\model\team\TeamFound;
use app\common\model\team\TeamJoin;
use app\common\model\user\User;
use app\common\model\user\UserLevel;
use app\common\server\UrlServer;
use app\common\model\seckill\SeckillGoods;
use app\common\model\bargain\BargainLaunch;
use app\common\model\user\UserAddress;
use app\common\server\AreaServer;
use app\common\server\ConfigServer;
use app\common\server\JsonServer;
use expressage\Kd100;
use expressage\Kdniao;
use think\Exception;
use think\facade\Db;
use think\facade\Env;

/**
 * Class OrderLogic
 * @package app\api\logic
 */
class OrderLogic extends Logic
{
    public static $order_type = OrderEnum::NORMAL_ORDER;

    /**
     * @notes 下单
     * @param $post
     * @return array|false
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\PDOException
     * @author suny
     * @date 2021/7/13 6:19 下午
     */
    public static function add($post)
    {
        // 初始化支付方式
        $post['pay_way'] = 0;
        if (!empty($post['goods'])) {
            $goods = is_array($post['goods']) ?  $post['goods'] : json_decode($post['goods'], true);
            $post['goods'] = $goods;
        } else {
            $where = [[
                'id', 'in', $post['cart_id']]
            ];
            $post['goods'] = $goods = Cart::where($where)
                ->field(['goods_id', 'item_id', 'shop_id', 'goods_num as num'])
                ->select()->toArray();
        }

        // 砍价订单验证
        if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
            self::$order_type = OrderEnum::BARGAIN_ORDER;
            $bargainLaunchModel = new BargainLaunch();
            $launch = $bargainLaunchModel->where(['id' => (int)$post['bargain_launch_id']])->find();
            if (!$launch) {
                throw new Exception('砍价异常');
            }
            if ($launch['status'] == 2) {
                throw new Exception('砍价失败,禁止下单');
            }
            if ($launch['payment_limit_time'] < time() and $launch['payment_limit_time'] > 0) {
                throw new Exception('下单失败,超出限制时间');
            }
            if ($launch['order_id'] > 0) {
                throw new Exception('您已下单了, 请勿重复操作');
            }
        }

        //检查商品上架状态及库存
        $check_goods = self::checkGoods($goods);
        Db::startTrans();
        try {
            if (false === $check_goods) {
                throw new Exception(self::$error);
            }
            $address = UserAddress::where('id', $post['address_id'])
                ->field('contact,telephone,province_id,city_id,district_id,address')
                ->find();
            if (empty($address)) {
                throw new Exception('请选择地址');
            }

            // 校验发票信息 返回以店铺id为键,原发票参数为值的数组
            $invoice = OrderInvoiceLogic::checkOrderInvoice($post);
            if (false === $invoice) {
                throw new Exception(OrderInvoiceLogic::getError());
            }

            $order_trade_add = self::addOrderTrade($post, $address);

            if (false === $order_trade_add) {
                throw new Exception('父订单创建失败');
            }
            $shop_goods = [];
            $order_goods_datas_insert = [];
            $order_log_datas_insert = [];
            foreach ($post['goods'] as $key => $value) { //按店铺区分商品
                $res = self::checkShop($value); //判断商家营业状态
                if ($res !== true) {
                    throw new Exception($res);
                }
                $shop_goods[$value['shop_id']][] = $value;
            }

            foreach ($shop_goods as $key => $value) {
                foreach ($value as $val) {
                    $seckill_goods_price = GoodsItem::isSeckill($val['item_id']);
                    if ($seckill_goods_price != 0) {//是秒杀商品
                        $sales_sum_res = self::setSeckillSaleSum($val['item_id'], $val['num']);
                        if ($sales_sum_res !== true) {
                            throw new Exception('秒杀商品销量设置失败');
                        }
                    }
                }

                $order_add = self::addOrder($order_trade_add, $value, $post, $key, $address);

                if (false === $order_add) {
                    throw new Exception('订单生成失败');
                }

                // 增加发票
                OrderInvoiceLogic::insertOrderInvoice($key, $post['user_id'], $order_add, $invoice);

                $order_log_add_data = self::getOrderLogData($key, $post['user_id'], $key);
                $order_log_datas_insert[] = $order_log_add_data;
                $order_goods_data = self::getOrderGoodsData($order_add, $value,$post['user_id']);
                $order_goods_datas_insert = array_merge($order_goods_datas_insert, $order_goods_data);
            }

            $order_log_insert = OrderLog::insertAll($order_log_datas_insert);

            if (false === $order_log_insert) {
                throw new Exception('订单日志生成失败');
            }

            $order_goods_inster = OrderGoods::insertAll($order_goods_datas_insert);

            if (false === $order_goods_inster) {
                throw new Exception('订单商品生成失败');
            }
            //商品库存减少
            $sub_goods_stock = self::subGoodsStock($post['goods']);
            if (false === $sub_goods_stock) {
                throw new Exception('库存修改失败');
            }

            //购物车删除
            if (isset($post['cart_id']) && $post['cart_id'] != 0) {
                $delCart = self::delCart($post['cart_id']);
                if (false === $delCart) {
                    throw new Exception('购物车删除失败');
                }
            }

            // 砍价订单处理
            if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
                $bargainLaunchModel = new BargainLaunch();
                $bargainLaunchModel->where(['id' => (int)$post['bargain_launch_id']])
                    ->update(['order_id' => $order_add, 'status' => 1]);
            }

            // 检测包邮活动
            $orders = Db::name('order')->where('trade_id', $order_trade_add)->select()->toArray();
            foreach($orders as $item) {
                $address = [
                    'province_id' => $item['province'],
                    'city_id' => $item['city'],
                    'district_id' => $item['district'],
                ];
                if(self::isFreeShipping($item['shop_id'], ($item['goods_price'] - $item['discount_amount']), $address)) {
                    // 符合包邮条件,去邮费
                    Db::name('order')->where('id', $item['id'])->update([
                        'order_amount' => $item['order_amount'] - $item['shipping_price'],
                        'total_amount' => $item['total_amount'] - $item['shipping_price'],
                        'shipping_price' => 0,
                    ]);
                }
            }
            // 更新主订单金额
            $newOrderAmount = Db::name('order')->where('trade_id', $order_trade_add)->sum('order_amount');
            $newTotalAmount = Db::name('order')->where('trade_id', $order_trade_add)->sum('total_amount');
            Db::name('order_trade')->where('id', $order_trade_add)->update([
                'order_amount' => $newOrderAmount,
                'total_amount' => $newTotalAmount,
            ]);

            Db::commit();
            return ['trade_id' => $order_trade_add, 'order_id' => $order_add, 'type' => 'trade'];
        } catch (Exception $e) {
            Db::rollback();
            self::$error = $e->getMessage();
            return false;
        }
    }

    /**
     * @notes 结算页数据
     * @param $post
     * @return array|false
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:19 下午
     */
    public static function settlement($post)
    {
        if (!empty($post['goods'])) {
            $goods = json_decode($post['goods'], true);
            $post['goods'] = $goods;
        } else {
            $where = [[
                'id', 'in', $post['cart_id']]
            ];
            $post['goods'] = $goods = Cart::where($where)
                ->field(['goods_id', 'item_id', 'shop_id', 'goods_num as num'])
                ->select()->toArray();
        }


        // 检查店铺营业状态
        foreach($post['goods'] as $good) {
            $shop = Shop::field('name,expire_time,is_run,is_freeze')->where(['del' => 0, 'id' => $good['shop_id']])->findOrEmpty();
            if($shop->isEmpty()) {
                self::$error = '部分商品所属店铺不存在';
                return false;
            }
            // 获取原始数据(不经获取器)
            $shop = $shop->getData();
            if(!empty($shop['expire_time']) && ($shop['expire_time'] <= time())) {
                self::$error = '部分商品所属店铺已到期';
                return false;
            }
            if($shop['is_freeze']) {
                self::$error = '部分商品所属店铺已被冻结';
                return false;
            }
            if(!$shop['is_run']) {
                self::$error = '部分商品所属店铺暂停营业中';
                return false;
            }
        }
        $Goods = new Goods();
        $GoodsItem = new GoodsItem();
        $Shop = new Shop();
        if (isset($post['address_id']) && !empty($post['address_id'])) {
            $where = [
                'id' => $post['address_id'],
                'del' => 0,
            ];
            $address = UserAddress::where($where)
                ->field('id,contact,telephone,province_id,city_id,district_id,address')
                ->find()->toArray();
        } else {
            $address = UserAddress::where(['user_id' => $post['user_id'], 'is_default' => 1,'del' => 0])
                ->field('id,contact,telephone,province_id,city_id,district_id,address')
                ->find();
        }
        if (!empty($address)) {
            $address['province'] = AreaServer::getAddress($address['province_id']);
            $address['city'] = AreaServer::getAddress($address['city_id']);
            $address['district'] = AreaServer::getAddress($address['district_id']);
        } else {
            $address = [];
        }

        // 校验发票信息 返回以店铺id为键,原发票参数为值的数组
        $invoice = OrderInvoiceLogic::checkOrderInvoice($post);
        if (false === $invoice) {
            self::$error = OrderInvoiceLogic::getError();
            return false;
        }

        foreach ($goods as &$good) {
            $goods_item = $GoodsItem->alias('gi')
                ->join('goods g', 'g.id = gi.goods_id')
                ->where(['gi.id' => $good['item_id'], 'gi.goods_id' => $good['goods_id']])
                ->field('gi.price,gi.spec_value_str,gi.image,g.image,g.name as goods_name, g.type as goods_type')
                ->find()
                ->toArray();
            $good['type'] = $goods_item['goods_type'];
            $good['name'] = $goods_item['goods_name'];
            $good['price'] = $goods_item['price'];
            $good['spec_value'] = $goods_item['spec_value_str'];
            $good['image'] = empty($goods_item['image']) ? $goods_item['image'] : $goods_item['image'];
            $good['image'] = UrlServer::getFileUrl($good['image']);
        }

        $shop = [];

        foreach ($goods as $key => $value) { //按店铺区分商品
            $shop_data = $Shop->where('id', $value['shop_id'])->find();
            $shop[$value['shop_id']]['shop_id'] = $value['shop_id'];
            $shop[$value['shop_id']]['shop_name'] = $shop_data['name'];
            $shop[$value['shop_id']]['open_invoice'] = $shop_data['open_invoice']; // 发票开关
            $shop[$value['shop_id']]['spec_invoice'] = $shop_data['spec_invoice']; // 是否支持专票
            $shop[$value['shop_id']]['delivery_type_text'] = Order::getDeliveryType(OrderEnum::DELIVERY_TYPE_EXPRESS);
            $shop[$value['shop_id']]['delivery_type'] = OrderEnum::DELIVERY_TYPE_EXPRESS;

            // 虚拟商品, 配送方式为 虚拟发货
            if ($value['type'] == GoodsEnum::TYPE_VIRTUAL) {
                $shop[$value['shop_id']]['delivery_type_text'] = Order::getDeliveryType(OrderEnum::DELIVERY_TYPE_VIRTUAL);
                $shop[$value['shop_id']]['delivery_type'] = OrderEnum::DELIVERY_TYPE_VIRTUAL;
            }

            $array = $post;
            $array['shop_id'] = $value['shop_id'];
            $shop_coupon_list = CouponLogic::getShopCouponList($array);
            $shop[$value['shop_id']]['coupon_list'] = $shop_coupon_list['suit'];
            //是否为秒杀
            $seckill_goods_price = GoodsItem::isSeckill($value['item_id']);
            if ($seckill_goods_price != 0) {
                $value['price'] = $seckill_goods_price;
                self::$order_type = OrderEnum::SECKILL_ORDER;  //秒杀订单
            }

            // 如果是砍价的商品,则替换信息
            if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
                $bargainLaunchModel = new BargainLaunch();
                $launch = $bargainLaunchModel->field(true)
                    ->where(['id' => (int)$post['bargain_launch_id']])
                    ->find();

                $bargainImage = $launch['goods_snap']['image'] == '' ? $launch['goods_snap']['goods_iamge'] : $launch['goods_snap']['image'];
                $value['goods_name'] = $launch['goods_snap']['name'];
                $value['image_str'] = UrlServer::getFileUrl($bargainImage);
                $value['price'] = $launch['current_price'];
                $value['spec_value_str'] = $launch['goods_snap']['spec_value_str'];
                self::$order_type = OrderEnum::BARGAIN_ORDER;//砍价订单
            }

            $shop[$value['shop_id']]['goods'][] = $value;
            $shop[$value['shop_id']]['shipping_price'] = self::calculateFreight($shop[$value['shop_id']]['goods'], $address);

            $user = User::where('id', $post['user_id'])->find();
            $discount = UserLevel::where(['id' => $user['level'],'del' => 0])->value('discount');

            // 普通订单才参与会员价
            if (self::$order_type == OrderEnum::NORMAL_ORDER) {
                if($discount == 0){
                    $discount = 10;
                }
                $shop[$value['shop_id']]['total_amount'] = round(self::calculateGoodsPrice($shop[$value['shop_id']]['goods'],$discount) + $shop[$value['shop_id']]['shipping_price'], 2);
            } else {
                $shop[$value['shop_id']]['total_amount'] = round(round($value['price'] * $value['num'], 2) + $shop[$value['shop_id']]['shipping_price'], 2);
            }

            //优惠券
            $discount_amount = 0;
            if (isset($post['coupon_id']) && !empty($post['coupon_id'])) {
                $result = self::checkCoupon($post['coupon_id'], $value['shop_id']);
                if ($result) {
                    $discount_amount = self::getDiscountAmount($post['coupon_id'], $value['shop_id'])['money'] ?? 0;
                }
            }
            $shop[$value['shop_id']]['discount_amount'] = $discount_amount;
            if ($shop[$value['shop_id']]['total_amount'] > $discount_amount) {
                $shop[$value['shop_id']]['total_amount'] = round($shop[$value['shop_id']]['total_amount'] - $discount_amount, 2);
            } else { //优惠金额大于当前商品总价,总价为0
                $shop[$value['shop_id']]['total_amount'] = 0;
            }

            $num = 0;
            foreach ($shop[$value['shop_id']]['goods'] as &$item) {
                $is_member = Goods::where('id',$item['goods_id'])->value('is_member');
                $price_sum = round($item['price'] * $item['num'],2);

                // 商品参与会员价 并且订单是 普通订单
                if ($is_member && self::$order_type == OrderEnum::NORMAL_ORDER) {
                    $item['is_member'] = 1;
                } else {
                    $item['is_member'] = 0;
                }

                if($item['is_member']) {
                    $member_amount = round($item['price']*$discount/10,2);
                    $item['member_amount'] = $member_amount;
                    $price_sum = round($member_amount * $item['num'],2);
                }
                $item['sum_price'] = $price_sum;
                $num += $item['num'];
            }
            $shop[$value['shop_id']]['total_num'] = $num;
        }

        $shop = array_values($shop);
        $total_amount = array_sum(array_column($shop, 'total_amount'));
        $orders['address'] = $address;
        $orders['shop'] = $shop;
        $orders['order_type'] = self::$order_type;
        $orders['total_amount'] = $total_amount;
        $orders['pay_way_text'] = "微信支付";
        $orders['pay_way'] = OrderEnum::PAY_WAY_WECHAT;

        // 检验是否参与包邮活动,若参与去除邮费
        $orders = self::checkFreeShipping($orders);
        // 重新算总价
        $orders['total_amount'] = array_sum(array_column($orders['shop'], 'total_amount'));

        $orders['invoice'] = array_values($invoice);

        return $orders;
    }

    /**
     * @notes 校验是否符合包邮条件
     * @param $orders
     * @author Tab
     * @date 2021/8/31 15:11
     */
    public static function checkFreeShipping($orders)
    {
        if (empty($orders['address'])) {
            return $orders;
        }
        $address = $orders['address'];
        foreach($orders['shop'] as &$item) {
            if (self::isFreeShipping($item['shop_id'], ($item['total_amount'] - $item['shipping_price']), $address)) {
                // 原总价格已算上邮费需减掉
                $item['total_amount'] = $item['total_amount'] - $item['shipping_price'];
                // 符合包邮条件,去邮费
                $item['shipping_price'] = 0;
            }
        }
        return $orders;
    }

    /**
     * @notes 是否满足包邮条件
     * @param $shopId 店铺ID
     * @param $orderAmount 订单金额
     * @param $address 地址
     * @return bool
     * @author Tab
     * @date 2021/8/31 15:42
     */
    public static function isFreeShipping($shopId, $orderAmount, $address)
    {
        $config = Db::name('free_shipping_config')->where([
            'shop_id' => $shopId,
            'del' => 0
        ])->findOrEmpty();
        if (empty($config) || $config['status'] == 0) {
            // 未设置 或 未开启包邮活动
            return false;
        }
        // 校验区级设置
        $district = Db::name('free_shipping_region')->where([
            'shop_id' => $shopId,
            'del' => 0
        ])->whereFindInSet('region', $address['district_id'])->findOrEmpty();
        if (!empty($district) && $orderAmount >= $district['order_amount']) {
            // 符合包邮条件
            return true;
        }
        if (!empty($district) && $orderAmount < $district['order_amount']) {
            // 不符合条件,不再校验市级
            return false;
        }
        // 校验市级设置
        $city = Db::name('free_shipping_region')->where([
            'shop_id' => $shopId,
            'del' => 0
        ])->whereFindInSet('region', $address['city_id'])->findOrEmpty();
        if (!empty($city) && $orderAmount >= $city['order_amount']) {
            // 符合包邮条件
            return true;
        }
        if (!empty($city) && $orderAmount < $city['order_amount']) {
            // 不符合条件,不再校验省级
            return false;
        }

        // 校验省级设置
        $province = Db::name('free_shipping_region')->where([
            'shop_id' => $shopId,
            'del' => 0
        ])->whereFindInSet('region', $address['province_id'])->findOrEmpty();
        if (!empty($province) && $orderAmount >= $province['order_amount']) {
            // 符合包邮条件
            return true;
        }
        if (!empty($province) && $orderAmount < $province['order_amount']) {
            // 不符合条件,不再校验全国设置
            return false;
        }

        // 校验全国设置
        $all = Db::name('free_shipping_region')->where([
            'shop_id' => $shopId,
            'del' => 0,
            'region' => 'all'
        ])->findOrEmpty();
        if (!empty($all) && $orderAmount >= $all['order_amount']) {
            // 符合包邮条件
            return true;
        }
        return false;
    }

    /**
     * @notes 获取优惠金额
     * @param $coupon_id
     * @return int|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:19 下午
     */
    public static function getDiscountAmount($coupon_id, $shopId = null)
    {
        $result = [
            'money' => 0,
            'shop_id' => $shopId,
            'coupon_list_id' => 0,
        ];

        if (!isset($coupon_id) || empty($coupon_id)) {
            return $result;
        }

        //优惠金额
        foreach ($coupon_id as $item) {
            $Coupon_list = CouponList::where('id', $item)->find();
            if (is_null($shopId)) {
                $where = ['id' => $Coupon_list['coupon_id'], 'del' => 0];
            } else {
                $where = ['id' => $Coupon_list['coupon_id'], 'del' => 0, 'shop_id' => $shopId];
            }
            $coupon = Coupon::where($where)
                ->find();
            if (!empty($coupon)) {
                $result['money'] = $coupon['money'];
                $result['shop_id'] = $shopId;
                $result['coupon_list_id'] = $item;
            }
        }
        return $result;
    }

    /**
     * @notes shop优惠券
     * @param $coupon_ids
     * @param $shop_id
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:20 下午
     */
    public static function checkCoupon($coupon_ids, $shop_id)
    {

        $coupons = CouponList::where([['id', 'in', $coupon_ids]])->select()->toArray();

        if ($coupons) {
            foreach ($coupons as $item) {
                $coupon_id = $item['coupon_id'];
                $where = [
                    'id' => $coupon_id
                ];
                $result = Coupon::where($where)->value('shop_id');
                if ($shop_id == $result) {
                    return true;
                }
            }
        } else {
            return false;
        }
    }

    /**
     * @notes 检查商品库存
     * @param $goods
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:20 下午
     */
    public static function checkGoods($goods)
    {

        if (!is_array($goods)) {
            self::$error = '商品数据格式不正确';
            return false;
        }
        $goods_item = new GoodsItem();
        $Good = new Goods();
        foreach ($goods as $key => $value) {
            $check_static = $Good->checkStatusById($value['goods_id']);
            $goods_name = $Good->where('id', $value['goods_id'])->value('name');
            if (false === $check_static) {
                self::$error = $goods_name . '商品不存在/未上架';
                return false;
            }
            $check_stock = $goods_item
                ->where([
                    ['goods_id', '=', $value['goods_id']],
                    ['id', '=', $value['item_id']],
                    ['stock', '<', $value['num']],
                ])
                ->find();
            if ($check_stock) {
                self::$error = '商品库存不足';
                return false;
            }
        }
        return true;
    }


    /**
     * @notes 计算商品总价格
     * @param $goods
     * @return false|float|int
     * @author suny
     * @date 2021/7/13 6:20 下午
     */
    public static function calculateGoodsPrice($goods,$discount)
    {


        if (!is_array($goods)) {
            return false;
        }
        $GoodsItem = new GoodsItem();
        $all_goods_price = 0;
        foreach ($goods as $key => $value) {
            $goods_price = $GoodsItem->sumGoodsPrice($value['goods_id'], $value['item_id'], $value['num'],$discount);
            $all_goods_price = round($goods_price + $all_goods_price, 2);
        }
        return $all_goods_price;
    }

    /**
     * @notes 计算会员折扣金额
     * @param $goods
     * @param $discount
     * @return false|float|int
     * @author suny
     * @date 2021/9/7 4:42 下午
     */
    public static function memberGoodsPrice($goods,$discount)
    {

        if (!is_array($goods)) {
            return false;
        }
        $GoodsItem = new GoodsItem();
        $all_goods_price = 0;
        foreach ($goods as $key => $value) {
            $goods_price = $GoodsItem->sumMemberPrice($value['goods_id'], $value['item_id'], $value['num'],$discount);
            $all_goods_price = round($goods_price + $all_goods_price, 2);
        }
        return $all_goods_price;
    }

    /**
     * @notes 根据goods计算商品总运费
     * @param $goods
     * @param $address
     * @return false|int|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:20 下午
     */
    public static function calculateFreight($goods, $address)
    {
        if (!is_array($goods)) {
            return 0;
        }

        $Goods = new Goods();
        $GoodsItem = new GoodsItem();
        $Freight = new Freight();
        $freight = 0;
        if (empty($address)) {
            return $freight;
        }

        foreach ($goods as $key => $value) {
            $express = $Goods->getExpressType($value['goods_id']);
            if ($express['express_type'] == 2) { //统一运费
                $price = $express['express_money'] * $value['num'];
//                $freight = bcadd($freight, $price, 2);
                $freight = round(($freight + $price), 2);
            }
            if ($express['express_type'] == 3) { //运费模板
                $goods_item = $GoodsItem->where([
                    ['goods_id', '=', $value['goods_id']],
                    ['id', '=', $value['item_id']]
                ])->field('stock,volume,weight')
                    ->find()
                    ->toArray();
                $price = $Freight->sumFreight($address, $goods_item, $express['express_template_id'], $value['num']);
//                $freight = bcadd($freight, $price, 2);
                $freight = round(($freight + $price), 2);
            }
        }
        return $freight;
    }

    /**
     * @notes 添加父订单
     * @param $post
     * @param $address
     * @return false|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author suny
     * @date 2021/7/13 6:20 下午
     */
    public static function addOrderTrade($post, $address)
    {

        $OrderTrade = new OrderTrade();
        $order_amount = 0;
        $total_amount = 0;
        //计算商品总价格
        $user = User::where('id', $post['user_id'])->find();
        $discount = UserLevel::where('id', $user['level'])->value('discount');
        if($discount == 0 || self::$order_type != OrderEnum::NORMAL_ORDER){
            $discount = 10;
        }
        $all_goods_price = self::calculateGoodsPrice($post['goods'],$discount);
        //计算商品运费
        $all_freight = self::calculateFreight($post['goods'], $address);
        $total_amount = $all_goods_price + $all_freight;

        //计算优惠券优惠的金额
        $discount_amount = 0;
        if (isset($post['coupon_id'])) {
            foreach ($post['goods'] as $value) {
                $discount_amount += self::getDiscountAmount($post['coupon_id'], $value['shop_id'])['money'] ?? 0;
            }
        }

        if ($total_amount > $discount_amount) {
            $total_amount = round(($total_amount - $discount_amount), 2);
        } else { //优惠金额大于当前商品总价,总价为0
            $total_amount = 0;
        }


        // 砍价订单
        if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
            foreach ($post['goods'] as $goods) {
                $bargainLaunchModel = new BargainLaunch();
                $launch = $bargainLaunchModel->field(true)
                    ->where(['id' => (int)$post['bargain_launch_id']])
                    ->find();
                $total_amount = round($launch['current_price'] * $goods['num'], 2);
            }
        }

        // 记录访问足迹
        event('Footprint', [
            'type' => FootprintEnum::PLACE_ORDER,
            'user_id' => $post['user_id'],
            'total_money' => $total_amount
        ]);
        $trade_order_data = [];
        $trade_order_data['t_sn'] = createSn('order_trade', 't_sn');

        // 拿shop_id,连接成字符串存入order_trade表shop_id中
        $shop_id = '';
        foreach ($post['goods'] as $key => $value) {
            $shop_id .= ',' . $value['shop_id'];
        }
        $shop_id = substr($shop_id, 1);
        $trade_order_data['shop_id'] = $shop_id;
        $trade_order_data['user_id'] = $post['user_id'];
        $trade_order_data['goods_price'] = $all_goods_price;
        $trade_order_data['order_amount'] = $total_amount;
        $trade_order_data['total_amount'] = $total_amount;
        $trade_order_data['discount_amount'] = $discount_amount;
        $trade_order_data['create_time'] = time();
        $order_trade_create = $OrderTrade->create($trade_order_data);
        if (false === $order_trade_create) {
            return false;
        }
        return $order_trade_create->id;
    }

    /**
     * @notes 添加子订单
     * @param $order_id
     * @param $goods
     * @param $post
     * @param $shop_id
     * @param $address
     * @return false|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author suny
     * @date 2021/7/13 6:21 下午
     */
    public static function addOrder($order_id, $goods, $post, $shop_id, $address)
    {
        $Order = new Order();

        $remarks = isset($post['remark']) ? json_decode($post['remark'], true) : '';
        if ($remarks != '') {
            foreach ($remarks as $key => $value) {
                $user_remark[$value['shop_id']] = $value['remark'];
            }
            if (array_key_exists($shop_id, $user_remark)) {
                $remark = $user_remark[$shop_id];
            } else $remark = '';
        } else {
            $remark = $remarks;
        }
        $user = User::where('id', $post['user_id'])->find();
        $discount = UserLevel::where('id', $user['level'])->value('discount');
        if($discount == 0 || self::$order_type != OrderEnum::NORMAL_ORDER){
            $discount = 10;
        }
        $goods_price = self::calculateGoodsPrice($goods,$discount); //商品价格
        $member_amount = self::memberGoodsPrice($goods,$discount); //会员优惠价格
        $shipping_price = self::calculateFreight($goods, $address);

        //计算优惠券优惠的金额
        $coupon_list_id = 0;
        $discount_amount = 0;
        if (isset($post['coupon_id'])) {
            $discount = self::getDiscountAmount($post['coupon_id'], $shop_id);
            $discount_amount = $discount['money'];
            $coupon_list_id = $discount['coupon_list_id'];
        }

        if($goods_price + $shipping_price <= $discount_amount){
            $total_amount = $order_amount = 0;
        }else{
            $total_amount = $order_amount = $goods_price + $shipping_price - $discount_amount;
        }

        // 砍价订单
        if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
            foreach ($post['goods'] as $post_goods) {
                $bargainLaunchModel = new BargainLaunch();
                $launch = $bargainLaunchModel->field(true)
                    ->where(['id' => (int)$post['bargain_launch_id']])
                    ->find();
                $order_amount = $total_amount = round($launch['current_price'] * $post_goods['num'], 2);
            }
        }

        $order_data = [];
        $order_data['trade_id'] = $order_id;
        $order_data['shop_id'] = $shop_id;
        $order_data['user_id'] = $post['user_id'];
        $order_data['order_sn'] = createSn('order_trade', 't_sn');
        $order_data['order_type'] = self::$order_type;
        $order_data['order_source'] = $post['client'];
        $order_data['order_status'] = OrderEnum::ORDER_STATUS_NO_PAID;
        $order_data['pay_status'] = OrderEnum::PAY_STATUS_NO_PAID;
        $order_data['pay_way'] = $post['pay_way'];
        $order_data['delivery_type'] = $post['delivery_type'] ?? 0;
        $order_data['aftersale_status'] = OrderEnum::AFTERSALE_STATUS_NO_SALE;
        $order_data['consignee'] = $address['contact'];
        $order_data['province'] = $address['province_id'];
        $order_data['city'] = $address['city_id'];
        $order_data['district'] = $address['district_id'];
        $order_data['address'] = $address['address'];
        $order_data['mobile'] = $address['telephone'];
        $order_data['goods_price'] = $goods_price;
        $order_data['shipping_price'] = $shipping_price;
        $order_data['order_amount'] = $order_amount;
        $order_data['discount_amount'] = $discount_amount;
        $order_data['member_amount'] = $member_amount;
        $order_data['total_amount'] = $total_amount;
        $order_data['total_num'] = array_sum(array_column($goods, 'num'));
        $order_data['user_remark'] = $remark;
        $order_data['distribution_money'] = 0;
        $order_data['coupon_list_id'] = $coupon_list_id;
        $order_data['create_time'] = time();

        $order_data['team_id'] = $user['team_id'];//订单所属团队

        // 前置订单
        $order_data['is_frontend'] = 0;
        if (!empty($post['is_frontend'])) {
            $order_data['is_frontend'] = 1;
            $order_data['order_status'] = OrderEnum::ORDER_STATUS_DELIVERY;
            $order_data['pay_status'] = OrderEnum::PAY_STATUS_PAID;
            $order_data['pay_way'] = OrderEnum::PAY_WAY_OFFLINE;
            $order_data['pay_time'] = time();
        }

        $order_create = $Order->create($order_data);

        if (false === $order_create) {
            return false;
        }

        if (!empty($coupon_list_id)) {
            self::editCoupon($coupon_list_id, $order_create->id);
        }

        return $order_create->id;
    }


    /**
     * @notes 添加订单商品
     * @param $order_id
     * @param $goods
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:21 下午
     */
    public static function getOrderGoodsData($order_id, $goods,$user_id)
    {
        $user = User::where('id', $user_id)->find();
        $discount = UserLevel::where('id', $user['level'])->value('discount');
        if($discount == 0 || self::$order_type != OrderEnum::NORMAL_ORDER){
            $discount = 10;
        }
        $goods_data = [];
        foreach ($goods as $key => $value) {
            $Goods = Goods::where('id', $value['goods_id'])->field('name,image,shop_id')->find();
            $GoodsItem = GoodsItem::where([
                ['id', '=', $value['item_id']],
                ['goods_id', '=', $value['goods_id']],
            ])->field('price,image,spec_value_ids,spec_value_str')
                ->find();
            $goods_data[$key]['order_id'] = $order_id;
            $goods_data[$key]['shop_id'] = $Goods['shop_id'];
            $goods_data[$key]['goods_id'] = $value['goods_id'];
            $goods_data[$key]['item_id'] = $value['item_id'];
            $goods_data[$key]['goods_num'] = $value['num'];
            $goods_data[$key]['goods_name'] = $Goods['name'];
            $goods_data[$key]['goods_price'] = $GoodsItem['price'];
            $goods_data[$key]['total_price'] = round($GoodsItem['price'] * $value['num'],2);
            $goods_data[$key]['total_pay_price'] = self::calculateGoodsPrice([$value],$discount);
            $goods_data[$key]['spec_value'] = $GoodsItem['spec_value_str'];
            $goods_data[$key]['spec_value_ids'] = $GoodsItem['spec_value_ids'];
            $goods_data[$key]['image'] = !empty($Goods['image']) ? UrlServer::setFileUrl($Goods['image']) : '';
            $goods_data[$key]['create_time'] = time();
        }
        $goods_data = self::shareDiscount($goods_data, $order_id);

        return $goods_data;
    }

    public static function shareDiscount($goodsData, $orderId)
    {
        // 获取订单优惠价格
        $orderDiscount = Order::where('id', $orderId)->value('discount_amount');
        if ($orderDiscount <= 0) {
            // 未使用优惠
            foreach ($goodsData as $key => &$item) {
                $item['discount_price'] = 0;
            }
            return $goodsData;
        }
        // 累计应付总金额
        $sumPayPrice = 0;
        foreach ($goodsData as $item) {
            $sumPayPrice += $item['total_pay_price'];
        }
        // 根据比例分摊优惠金额
        $sumDiscount = 0;
        foreach ($goodsData as $key => &$item) {
            if ($key == (count($goodsData) - 1)) {
                // 最后一条记录
                $item['discount_price'] = $orderDiscount - $sumDiscount;
            }
            $item['discount_price'] = round($item['total_pay_price'] / $sumPayPrice * $orderDiscount, 2);
            $item['total_pay_price'] -=  $item['discount_price'];
            $sumDiscount .+ $item['discount_price'];
        }

        return $goodsData;
    }

    /**
     * @notes 扣除商品库存
     * @param $goods
     * @return bool
     * @author suny
     * @date 2021/7/13 6:21 下午
     */
    public static function subGoodsStock($goods)
    {
        $goods_ids = [];

        foreach ($goods as $key => $value) {
            $goods_item_stock_dec = GoodsItem::where([
                ['id', '=', $value['item_id']],
                ['goods_id', '=', $value['goods_id']],
            ])->dec('stock', $value['num'])
                ->update();
            $goods_stock_dec = Goods::where('id', $value['goods_id'])
                ->dec('stock', $value['num'])
                ->update();
            if (false === $goods_item_stock_dec) {
                return false;
            }
            if (false === $goods_stock_dec) {
                return false;
            }

            $goods_ids[] = $value['goods_id'];
        }

        // 下架总库存为0商品
        self::outGoods($goods_ids);

        return true;
    }


    /**
     * @notes 下架总库存为0商品
     * @param $goods_ids
     * @return bool|void
     * @author 段誉
     * @date 2021/12/21 14:46
     */
    public static function outGoods($goods_ids)
    {
        try{
            $goods = Goods::where('id', 'in', $goods_ids)
                ->field('id, stock')
                ->select();

            if (empty($goods)) {
                return true;
            }

            $need_handle_ids = [];
            foreach ($goods as $good) {
                if ($good['stock'] <= 0) {
                    $need_handle_ids[] =  $good['id'];
                }
            }

            if (empty($need_handle_ids)){
                return true;
            }
            //下架订单商品中 商品总库存已为0的商品
            Goods::where('id', 'in', $need_handle_ids)->update(['status' => 0]);

            // 下架或删除商品更新收藏状态
            event('UpdateCollect', ['goods_id' => $need_handle_ids]);

        } catch (\Exception $e) {}
    }


    /**
     * @notes 添加订单日志表
     * @param $order_id
     * @param $user_id
     * @param $shop_id
     * @return array
     * @author suny
     * @date 2021/7/13 6:21 下午
     */
    public static function getOrderLogData($order_id, $user_id, $shop_id)
    {

        $order_log_data = [];
        $order_log_data['type'] = OrderLogEnum::TYPE_USER;
        $order_log_data['channel'] = OrderLogEnum::USER_ADD_ORDER;
        $order_log_data['order_id'] = $order_id;
        $order_log_data['handle_id'] = $user_id;
        $order_log_data['shop_id'] = $shop_id;
        $order_log_data['content'] = OrderLogEnum::USER_ADD_ORDER;
        $order_log_data['create_time'] = time();

        return $order_log_data;

    }

    /**
     * @notes 删除购物车
     * @param $cart_id
     * @return bool
     * @author suny
     * @date 2021/7/13 6:21 下午
     */
    public static function delCart($cart_id)
    {

        $delCart = Cart::where([
            ['id', 'in', $cart_id],
            ['selected', '=', 1]
        ])
            ->delete();
        if (false === $delCart) {
            return false;
        }
        return true;

    }

    /**
     * @notes 订单列表
     * @param $user_id
     * @param $type
     * @param $page
     * @param $size
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:21 下午
     */
    public static function getOrderList($user_id, $type, $page, $size)
    {

        $order = new Order();
        $where[] = ['del', '=', 0];
        $where[] = ['user_id', '=', $user_id];

        switch ($type) {
            case 'pay':
                $where[] = ['order_status', '=', OrderEnum::ORDER_STATUS_NO_PAID];
                break;
            case 'delivery':
                $where[] = ['order_status', 'in', [OrderEnum::ORDER_STATUS_DELIVERY, OrderEnum::ORDER_STATUS_GOODS]];
                break;
            case 'finish':
                $where[] = ['order_status', '=', OrderEnum::ORDER_STATUS_COMPLETE];
                break;
            case 'close':
                $where[] = ['order_status', '=', OrderEnum::ORDER_STATUS_DOWN];
                break;
        }

        $count = $order->where(['del' => 0, 'user_id' => $user_id])
            ->where($where)
            ->count();

        $lists = $order->where(['del' => 0, 'user_id' => $user_id])
            ->where($where)
            ->with(['order_goods', 'shop'])
            ->field('id,order_sn,order_status,pay_status,order_amount,order_status,order_type,shipping_status,create_time,shop_id,delivery_type,frontend_info,is_frontend')
            ->page($page, $size)
            ->order('id desc')
            ->select();

        $lists->append(['goods_count', 'pay_btn', 'cancel_btn', 'delivery_btn', 'take_btn', 'del_btn', 'comment_btn', 'content_btn','order_cancel_time']);

        foreach ($lists as $k => $list) {
            if ($list['order_type'] == OrderEnum::SECKILL_ORDER) {//如果是秒杀
                foreach ($list['order_goods'] as $item) {
                    $seckill_price = GoodsItem::isSeckill($item['item_id']);
                    if ($seckill_price != 0) {
                        $item['goods_price'] = $seckill_price;
                    }
                }
            }
            $lists[$k]['frontend_array'] = array_filter(explode(',', $list['frontend_info']));
        }
        $data = [
            'list' => $lists,
            'page' => $page,
            'size' => $size,
            'count' => $count,
            'more' => is_more($count, $page, $size)
        ];
        return $data;
    }

    /**
     * @notes 通过规格id查询秒杀价格
     * @param $item_id
     * @return int|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:21 下午
     */
    public static function getSekillPriceByItemId($item_id)
    {

        $where = [
            'item_id' => $item_id,
            'del' => 0,
            'review_status' => 1
        ];
        $seckill = SeckillGoods::where($where)->find();
        return isset($seckill['price']) ? $seckill['price'] : 0;
    }

    /**
     * @notes 订单详情
     * @param $order_id
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:22 下午
     */
    public static function getOrderDetail($order_id)
    {

        $order = Order::with(['order_goods', 'shop'])->where(['del' => 0, 'id' => $order_id])->find();
        if ($order) {
            $order->append(['delivery_address', 'pay_btn', 'cancel_btn', 'delivery_btn', 'take_btn', 'del_btn','view_invoice_btn','save_invoice_btn', 'order_cancel_time'])
                ->hidden(['user_id', 'order_source',
                    'city', 'district', 'address', 'shipping_status', 'shipping_code',
                    'pay_status', 'transaction_id', 'del', 'province']);

            $refund_days = ConfigServer::get('after_sale', 'refund_days', 7 * 86400, 0) * 86400;
            $now = time();
            foreach ($order->order_goods as $order_good) {
                if ($order['order_type'] == OrderEnum::SECKILL_ORDER) { // 是秒杀商品
                    $seckill_price = GoodsItem::isSeckill($order_good['item_id']);
                    if ($seckill_price != 0) {
                        $order_good['goods_price'] = $seckill_price;
                    }
                }$order_good['sum_price'] = $order_good['goods_price'] * $order_good['goods_num'];
                $order_good['comment_btn'] = 0;
                if ($order['pay_status'] == PayEnum::ISPAID && $order['order_status'] == OrderEnum::ORDER_STATUS_COMPLETE && $order_good['is_comment'] == 0) {
                    $order_good['comment_btn'] = 1;
                }
                $order_good['refund_btn'] = 0;

                $confirm_take_time = strtotime($order['confirm_take_time']) ?: 0;
                $refund_time = $confirm_take_time + $refund_days;
                if ($order['order_status'] == OrderEnum::ORDER_STATUS_COMPLETE && $order_good['refund_status'] == OrderGoodsEnum::REFUND_STATUS_NO) {
                    $order_good['refund_btn'] = 1;
                }
                $order_good['sum_price'] = $order_good['goods_price'] * $order_good['goods_num'];
            }
        }

        // 如果是拼团的订单
        if ($order['order_type'] == OrderEnum::TEAM_ORDER) {
            $teamJoin = (new TeamJoin())->where(['order_id' => $order['id']])->findOrEmpty()->toArray();
            $teamJoin['team_snap'] = json_decode($teamJoin['team_snap'], true);
            $order['team'] = [
                'team_activity_id' => $teamJoin['team_activity_id'],
                'team_id' => $teamJoin['team_id'],
                'identity' => $teamJoin['identity'] == 1 ? '团长' : '团员',
                'people_num' => $teamJoin['team_snap']['people_num'],
                'status' => $teamJoin['status'],
                'status_text' => TeamEnum::getStatusDesc($teamJoin['status'])
            ];
        }

        $order['order_type'] = Order::getOrderType($order['order_type']);
        $order['pay_way'] = PayEnum::getPayWay($order['pay_way']);
        $order['create_time'] = $order['create_time'] == 0 ? '' : $order['create_time'];
        $order['update_time'] = $order['update_time'] == 0 ? '' : $order['update_time'];
        $order['confirm_take_time'] = $order['confirm_take_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['confirm_take_time']);;
        $order['shipping_time'] = $order['shipping_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['shipping_time']);
        $order['pay_time'] = $order['pay_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['pay_time']);
        $order['cancel_time'] = $order['cancel_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['cancel_time']);

        // 虚拟商品 发货内容
        if ($order['delivery_type'] != OrderEnum::DELIVERY_TYPE_VIRTUAL || $order['shipping_status'] != OrderEnum::SHIPPING_FINISH) {
            $order['delivery_content'] = '';
        }

        $frontendArray = explode(',',trim($order['frontend_info']));
        $order['frontend_array'] = array_filter($frontendArray);

        return $order->toArray();
    }

    /**
     * @notes 取消订单
     * @param $order_id
     * @param $user_id
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\PDOException
     * @author suny
     * @date 2021/7/13 6:22 下午
     */
    public static function cancel($order_id, $user_id)
    {
        $time = time();
        $order = Order::with(['orderGoods'])->where(['del' => 0, 'user_id' => $user_id, 'id' => $order_id])->find();

        if (!$order || (int)$order['order_status'] > OrderEnum::ORDER_STATUS_DELIVERY) {
            return JsonServer::error('很抱歉!订单无法取消');
        }

        $cancel_limit = ConfigServer::get('transaction', 'paid_order_cancel_time', 0);
        $limit_time = strtotime($order['create_time']) + $cancel_limit * 60;
        if ($limit_time < time()) {
            return JsonServer::error('很抱歉!订单已不可取消');
        }

        Db::startTrans();
        try {
            // 如果是拼团的订单
            if ($order['order_type'] == OrderEnum::TEAM_ORDER) {

                $team_id = (new TeamJoin())->where(['order_id' => $order['id']])->value('team_id');
                $teamJoin = (new TeamJoin())->alias('TJ')
                    ->field(['TJ.*,O.order_sn,O.order_status,O.pay_status,O.refund_status,O.order_amount'])
                    ->where(['team_id' => $team_id])
                    ->join('order O', 'O.id=TJ.order_id')
                    ->select()->toArray();

                TeamFound::update(['status' => TeamEnum::TEAM_STATUS_FAIL, 'team_end_time' => $time], ['id' => $team_id]);
                foreach ($teamJoin as $item) {
                    TeamJoin::update(['status' => TeamEnum::TEAM_STATUS_FAIL, 'update_time' => $time], ['id' => $item['id']]);
                    OrderRefundLogic::cancelOrder($item['order_id'], OrderLogEnum::TYPE_USER, $user_id);  //取消订单

                    if ($item['pay_status'] == PayEnum::ISPAID) {
                        $order = (new Order())->findOrEmpty($item['order_id'])->toArray();
                        OrderRefundLogic::cancelOrderRefundUpdate($order); //更新订单状态
                        OrderRefundLogic::refund($order, $order['order_amount'], $order['order_amount']); //订单退款
                    }
                }


            } else {
                //取消订单
                OrderRefundLogic::cancelOrder($order_id, OrderLogEnum::TYPE_USER, $user_id);
                //已支付的订单,取消,退款
                if ($order['pay_status'] == PayEnum::ISPAID) {
                    //更新订单状态
                    OrderRefundLogic::cancelOrderRefundUpdate($order);
                    //订单退款
                    OrderRefundLogic::refund($order, $order['order_amount'], $order['order_amount']);
                }

            }

            Db::commit();
            return JsonServer::success('取消成功');
        } catch (Exception $e) {
            Db::rollback();
            self::addErrorRefund($order, $e->getMessage());
            return JsonServer::error($e->getMessage());
        }
    }

    /**
     * @notes 回退商品库存
     * @param $goods
     * @author suny
     * @date 2021/7/13 6:22 下午
     */
    public static function backStock($goods)
    {

        foreach ($goods as $good) {
            //回退库存,回退规格库存,减少商品销量
            Goods::where('id', $good['goods_id'])
                ->update([
                    'stock' => Db::raw('stock+' . $good['goods_num'])
                ]);

            //补充规格表库存
            GoodsItem::where('id', $good['item_id'])
                ->inc('stock', $good['goods_num'])
                ->update();
        }
    }

    /**
     * @notes 增加退款失败记录
     * @param $order
     * @param $err_msg
     * @return int|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author suny
     * @date 2021/7/13 6:22 下午
     */
    public static function addErrorRefund($order, $err_msg)
    {

        $orderRefund = new OrderRefund();
        $refund_data = [
            'order_id' => $order['id'],
            'user_id' => $order['user_id'],
            'refund_sn' => createSn('order_refund', 'refund_sn'),
            'order_amount' => $order['order_amount'],//订单应付金额
            'refund_amount' => $order['order_amount'],//订单退款金额
            'transaction_id' => $order['transaction_id'],
            'create_time' => time(),
            'refund_status' => 2,
            'refund_msg' => json_encode($err_msg, JSON_UNESCAPED_UNICODE),
        ];
        return $orderRefund->insertGetId($refund_data);
    }

    /**
     * @notes 获取退款订单的应付金额
     * @param $order
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:22 下午
     */
    public static function getOrderTotalFee($order)
    {

        $OrderTrade = new OrderTrade();
        $trade = $OrderTrade
            ->where('transaction_id', $order['transaction_id'])
            ->find();

        $total_fee = $order['order_amount'];
        if ($trade) {
            $total_fee = $trade['order_amount'];
        }
        return $total_fee;
    }


    /**
     * @notes 确认订单
     * @param $order_id
     * @param $user_id
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:22 下午
     */
    public static function confirm($order_id, $user_id)
    {

        $order = Order::where(['del' => 0, 'id' => $order_id])->find();
        if ($order['order_status'] == OrderEnum::ORDER_STATUS_COMPLETE) {
            return JsonServer::error('订单已完成');
        }
        if ($order['shipping_status'] == 0) {
            return JsonServer::error('订单未发货');
        }
        $order->order_status = OrderEnum::ORDER_STATUS_COMPLETE;
        $order->update_time = time();
        $order->confirm_take_time = time();
        $order->save();

        //订单日志
        OrderLogLogic::record(
            OrderLogEnum::TYPE_USER,
            OrderLogEnum::USER_CONFIRM_ORDER,
            $order_id,
            $user_id,
            OrderLogEnum::USER_CONFIRM_ORDER
        );

        return JsonServer::success('确认成功');
    }

    /**
     * @notes 删除订单
     * @param $order_id
     * @param $user_id
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function del($order_id, $user_id)
    {

        $where = [
            'order_status' => OrderEnum::ORDER_STATUS_DOWN,
            'user_id' => $user_id,
            'id' => $order_id,
            'del' => 0,
        ];
        $order = Order::where($where)->find();

        if (!$order) {
            return JsonServer::error('订单无法删除');
        }

//        $res = $order->save(['del' => 1, 'update_time' => time()]);
        $data = ['del' => 1, 'update_time' => time(), 'pat_status' => OrderEnum::ORDER_STATUS_DOWN];
        $res = Order::update($data, ['id' => $order['id']]);
        OrderLogLogic::record(
            OrderLogEnum::TYPE_USER,
            OrderLogEnum::USER_DEL_ORDER,
            $order_id,
            $user_id,
            OrderLogEnum::USER_DEL_ORDER
        );
        return JsonServer::success('删除成功', ['res' => $res]);
    }

    /**
     * @notes 获取订单支付结果
     * @param $trade_id
     * @return array|false
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function pay_result($id,$from)
    {
        switch ($from) {
            case 'trade' : //如果是父订单类型下单,$id为父订单id
                $result = OrderTrade::alias('ot')
                    ->where(['ot.id' => $id,'o.pay_status' => 1])
                    ->join('order o','o.trade_id = ot.id')
                    ->field(['ot.id', 'ot.t_sn as order_sn', 'o.pay_time', 'o.pay_way', 'ot.total_amount'])
                    ->findOrEmpty()
                    ->toArray();
                $result['total_amount'] = '¥' . $result['total_amount'];
                break;

            case 'order' : //如果是子订单类型下单,$id为子订单id
                $result = Order::where(['id' => $id])
                    ->field(['id', 'order_sn', 'pay_time', 'pay_way', 'total_amount'])
                    ->findOrEmpty()
                    ->toArray();
                $result['total_amount'] = '¥' . $result['total_amount'];
                break;

            case 'integral':
                $result = IntegralOrder::where(['id' => $id])
                    ->field(['id', 'order_sn', 'pay_time', 'pay_way', 'order_amount', 'order_integral', 'exchange_way'])
                    ->findOrEmpty()->toArray();
                $order_integral = $result['order_integral'] > 0 ? $result['order_integral'] . '积分' : '';
                $order_amount = $result['order_amount'] > 0 ? '+ ¥' . $result['order_amount'] . '元' : '';
                $result['total_amount'] = $order_integral . $order_amount;
                break;
            default :
                return false;
        }
        if ($result) {
            $result['pay_time'] = date('Y-m-d H:i:s', $result['pay_time']);
            $result['pay_way'] = PayEnum::getPayWay($result['pay_way']);
            return $result;
        }
        return false;
    }

    /**
     * @notes 获取支付方式
     * @param $user_id
     * @return array|array[]|\array[][]|\array[][][]
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function getPayWay($user_id, $client, $params)
    {

        $payModel = new Pay();
        $payway = $payModel->where(['status' => 1])->order('sort')->hidden(['config'])->select()->toArray();
        foreach ($payway as $k => &$item) {
            if ($item['code'] == 'wechat') {
                $item['extra'] = '微信快捷支付';
                $item['pay_way'] = PayEnum::WECHAT_PAY;
            }

            if ($item['code'] == 'balance') {
                $user_money = Db::name('user')->where(['id' => $user_id])->value('user_money');
                $item['extra'] = '可用余额:' . $user_money;
                $item['pay_way'] = PayEnum::BALANCE_PAY;
                if($params['from'] == 'recharge') {
                    unset($payway[$k]);
                }
            }

            if ($item['code'] == 'alipay') {
                $item['extra'] = '';
                $item['pay_way'] = PayEnum::ALI_PAY;
                if (in_array($client, [ClientEnum::mnp, ClientEnum::oa])) {
                    unset($payway[$k]);
                }
            }
        }

        if($params['from'] == 'order') {
            $order = Order::findOrEmpty($params['order_id']);
        } else if($params['from'] == 'trade') {
            $order = OrderTrade::findOrEmpty($params['order_id']);
        } else if($params['from'] == 'integral') {
            $order = IntegralOrder::findOrEmpty($params['order_id']);
        } else {
            $order = RechargeOrder::findOrEmpty($params['order_id']);
        }
        $cancelTime = ConfigServer::get('transaction', 'unpaid_order_cancel_time', '');
        if(empty($cancelTime) || $params['from'] == 'integral') {
            $cancelTime = 0;
        } else {
            $cancelTime = strtotime($order['create_time']) + intval($cancelTime) * 60;
        }
        return [
            'pay_way' => $payway,
            'order_amount' => $order['order_amount'],
            'cancel_time' => $cancelTime,
        ];
    }

    /**
     * @notes 查询物流
     * @param $id
     * @param $user_id
     * @return array|false
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function orderTraces($id, $user_id)
    {

        $order = new Order();
        $order = $order->alias('o')
            ->join('order_goods og', 'o.id = og.order_id')
            ->join('goods g', 'g.id = og.goods_id')
            ->where(['o.id' => $id, 'o.user_id' => $user_id, 'pay_status' => OrderEnum::ORDER_STATUS_DELIVERY, 'o.del' => 0])
            ->field('o.id,order_status,total_num,og.image,o.consignee,o.mobile,o.province,o.city,o.district,o.address,pay_time,confirm_take_time,o.shipping_status,shipping_time')
            ->append(['delivery_address'])
            ->find();
//        if (!self::checkDelivery($order['delivery_id'])) {
//            return false;
//        }
        //初始化数据
        $order_tips = '已下单';
        $order_traces = [];
        $traces = [];//物流轨迹
        $shipment = [//发货
            'title' => '已发货',
            'tips' => '',
            'time' => '',
        ];
        $finish = [//交易完成
            'title' => '交易完成',
            'tips' => '',
            'time' => '',
        ];

        if ($order) {
            $order_delivery = Delivery::where(['order_id' => $id])->field('invoice_no,shipping_name,shipping_id,mobile')->find();

            $express = ConfigServer::get('express', 'way', '', '');
            //已发货
            if ($express && $order['shipping_status']) {
                $key = ConfigServer::get($express, 'appkey');
                $app = ConfigServer::get($express, 'appsecret');
                //获取物流配置
                if ($app && $key) {
                    //快递配置设置为快递鸟时
                    if ($express === 'kdniao') {
                        $expressage = (new Kdniao($app, $key, Env::get('app.app_debug', 'true')));
                        $shipping_field = 'codebird';
                    } else {
                        $expressage = (new Kd100($app, $key, Env::get('app.app_debug', 'true')));
                        $shipping_field = 'code100';
                    }
                    //快递编码
                    $shipping_code = Db::name('express')->where(['id' => $order_delivery['shipping_id']])->value($shipping_field);
                    //获取物流轨迹
                    if ($shipping_code === 'SF' && $express === 'kdniao') {
                        $expressage->logistics($shipping_code, $order_delivery['invoice_no'], substr($order_delivery['mobile'],-4));
                    }else {
                        $expressage->logistics($shipping_code, $order_delivery['invoice_no']);
                    }
                    $traces = $expressage->logisticsFormat();
                    //获取不到物流轨迹时
                    if ($traces == false) {
                        $error = $expressage->getError();
                        $error = json_decode($error,true);
                        if ($express === 'kdniao') {
                            if($error['Success'] == false){
                                $traces[] = [$error['Reason']];
                            }
                        } else {
                            if($error['result'] == false){
                                $traces[] = [$error['message']];
                            }
                        }

                    } else {
                        foreach ($traces as &$item) {
                            $item = array_values(array_unique($item));
                        }
                    }

                }
            }
            //待收货
            if ($order['order_status'] == 2) {
                $shipment['tips'] = '商品已出库';
                $shipment['time'] = date('Y-m-d H:i:s', $order['shipping_time']);
            }
            //确认收货
            if ($order['order_status'] == 3) {
                $order_tips = '交易完成';
                $finish['tips'] = '订单交易完成';
                $finish['time'] = $order['confirm_take_time'] ? date('Y-m-d H:i:s', $order['confirm_take_time']) : $order['confirm_take_time'];
            }
            //数据合并
            $order_traces = [
                'order' => [
                    'tips' => $order_tips,
                    'image' => UrlServer::getFileUrl($order['image']),
                    'count' => $order['total_num'],
                    'invoice_no' => $order_delivery['invoice_no'],
                    'shipping_name' => empty($order_delivery['shipping_name']) ? '-' : $order_delivery['shipping_name'],
                ],
                'take' => [
                    'contacts' => $order['consignee'],
                    'mobile' => $order['mobile'],
                    'address' => $order['delivery_address'],
                ],
                'finish' => $finish,
                'delivery' => [
                    'title' => '运输中',
                    'traces' => $traces
                ],
                'shipment' => $shipment,
                'buy' => [
                    'title' => '已下单',
                    'tips' => '订单提交成功',
                    'time' => date('Y-m-d H:i:s', $order['pay_time'])
                ],
            ];
            return $order_traces;
        }

        return $order_traces;

    }

    /**
     * @notes 配送方式无需快递的
     * @param $delivery_id
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function checkDelivery($delivery_id)
    {

        $delivery = Delivery::where(['id' => $delivery_id])
            ->find();
        if ($delivery['send_type'] == 2) {
            return false;
        }
        return true;
    }

    /**
     * @notes 判断商家营业状态
     * @param $value
     * @return bool|string
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function checkShop($value)
    {
        $shop = Shop::where('id', $value['shop_id'])->field('is_run, is_pay')->findOrEmpty();
        if (!$shop['is_run']) {
            return '该商家已暂停营业';
        }

        if (!$shop['is_pay']) {
            return '该商家支付功能已关闭';
        }
        return true;
    }

    /**
     * @notes 修改优惠券状态
     * @param $coupon_id
     * @param $order_id
     * @return CouponList|false
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function editCoupon($coupon_id, $order_id)
    {

        $status = CouponList::where(['id' => $coupon_id, 'status' => 0])->find();
        if (!$status) {
            return false;
        }
        $time = time();
        $data = [
            'status' => 1,
            'use_time' => $time,
            'update_time' => $time,
            'order_id' => $order_id
        ];
        $res = CouponList::where('id', $status->id)
            ->update($data);
        return $res;
    }

    /**
     * @notes 设置秒杀商品销量
     * @param $item_id
     * @param $num
     * @return bool
     * @author suny
     * @date 2021/7/13 6:23 下午
     */
    public static function setSeckillSaleSum($item_id, $num)
    {

        $result = SeckillGoods::where('item_id', $item_id)
            ->inc('sales_sum', $num)
            ->save();
        if ($result) {
            return true;
        } else {
            return false;
        }
    }

    public static function getPayStatus($id,$from)
    {

        switch ($from){
            case 'trade' : //如果是父订单类型下单,$id为父订单id
                $order_trade = OrderTrade::alias('ot')
                    ->where(['ot.id' => $id])
                    ->join('order o','o.trade_id = ot.id')
                    ->field(['ot.id','o.id as order_id', 'ot.t_sn as order_sn', 'o.pay_time', 'o.pay_way', 'ot.total_amount','o.pay_status','o.order_status'])
                    ->select()
                    ->toArray();
                foreach ($order_trade as $item) {
                    if($item['pay_time']){
                        $item['pay_time'] = date('Y-m-d H:i:s', $item['pay_time']);
                    }
                    $create_time = Db::name('order')->where(['id' => $item['order_id']])->value('create_time');
                    $unpaid_order_cancel_time = ConfigServer::get('transaction','unpaid_order_cancel_time','30');
                    $cancel_time = $create_time + $unpaid_order_cancel_time * 60;
                    $item['pay_status_text'] = PayEnum::getPayStatus($item['pay_status']);
                    $result = $item;
                    $goods_lists = Db::name('order_goods')
                        ->where(['order_id' => $item['order_id']])
                        ->field('id,goods_name')
                        ->order('shop_id desc')
                        ->select()
                        ->toArray();
                    foreach ($goods_lists as $goods_list) {
                        $order_goods[] = $goods_list;
                    }
                    $order = Order::where(['id' => $item['order_id']])
                        ->find()
                        ->append(['pc_address'])
                        ->toArray();
                    $contact = $order['consignee'];
                    $mobile = $order['mobile'];
                    $address = [
                        'contact' => $contact,
                        'mobile' => $mobile,
                        'delivery_address' => $order['pc_address'],
                    ];

                    $pay_way_text = PayEnum::getPayWay($item['pay_way']);
                    $result['pay_way'] = $pay_way_text;
                    $result['cancel_time'] = $cancel_time;
                }
                $result['order_goods'] = $order_goods;
                $result['address'] = $address;
                break;

            case 'order' : //如果是子订单类型下单,$id为子订单id
                $result = Order::where(['id' => $id])
                    ->field(['id', 'order_sn', 'pay_time', 'pay_way', 'total_amount','consignee','mobile','province','city','district','address','pay_status','order_status'])
                    ->findOrEmpty()
                    ->append(['pc_address'])
                    ->toArray();
                $create_time = Db::name('order')->where(['id' => $id])->value('create_time');
                $unpaid_order_cancel_time = ConfigServer::get('transaction','unpaid_order_cancel_time','30');
                $cancel_time = $create_time + $unpaid_order_cancel_time * 60;
                $order_goods = Db::name('order_goods')
                    ->where(['order_id' => $result['id']])
                    ->field('id,goods_name')
                    ->order('shop_id desc')
                    ->select()
                    ->toArray();
                $contact = $result['consignee'];
                $mobile = $result['mobile'];
                $address = [
                    'contact' => $contact,
                    'mobile' => $mobile,
                    'delivery_address' => $result['pc_address'],
                ];
                $result['order_goods'] = $order_goods;
                $result['address'] = $address;
                $result['cancel_time'] = $cancel_time;
                if($result['pay_time']){
                    $result['pay_time'] = date('Y-m-d H:i:s', $result['pay_time']);
                }
                break;
            default :
                return false;
        }
        return $result;
    }
}