<?php
/**
 *  ╔═══════════════════════════════════════════════════╗
 *  ║                                                   ║
 *  ║     ██╗  ██╗   █████╗    ██████╗                  ║
 *  ║     ██║  ██║  ██╔══██╗  ██╔═══██╗                 ║
 *  ║     ███████║  ███████║  ██║   ██║                 ║
 *  ║     ██╔══██║  ██╔══██║  ██║   ██║                 ║
 *  ║     ██║  ██║  ██║  ██║  ╚██████╔╝   SNS           ║
 *  ║                                                   ║    
 *  ║                                                   ║    
 *  ║     © 2023 HaoSNS™ All Rights Reserved            ║
 *  ║     官方网站: https://www.haosns.com                *
 *  ║     本代码由赣州乐易网络科技有限公司®提供             *
 *  ║                                                    *
 *  ║   未经授权禁止复制、传播或用于其他商业目的            *
 *  ║                                                   ║
 *  ╚═══════════════════════════════════════════════════╝
 */


namespace app\common\service\after_sale;

use app\common\enum\AfterSaleEnum;
use app\common\enum\AfterSaleLogEnum;
use app\common\enum\OrderEnum;
use app\common\enum\YesNoEnum;
use app\common\logic\RefundLogic;
use app\common\model\AfterSale;
use app\common\model\AfterSaleLog;
use app\common\model\AfterSaleGoods;
use app\common\model\Goods;
use app\common\model\GoodsItem;
use app\common\model\Order;
use app\common\model\OrderGoods;
use app\common\service\ConfigService;

/**
 * 售后服务类
 * Class AfterSaleService
 * @package app\common\service
 */
class AfterSaleService
{
    /**
     * @notes  整单退款
     * 调用者需开启事务以保证数据写入的一致性
     * @param $params array order_id 订单号 、 scene 场景 1-买家取消订单 2-卖家取消订单 3-支付加调时订单已取消
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function orderRefund($params)
    {
        // 校验是否允许发起整单退款
        self::checkCondition($params);

        // 生成售后记录
        self::createAfterSale($params);
    }

    /**
     * @notes 校验是否允许发起整单退款
     * @param $orderId 订单号
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function checkCondition($params)
    {
        $order = Order::findOrEmpty($params['order_id']);
        if($order->isEmpty()) {
            throw new \think\Exception('订单不存在,无法发起整单退款');
        }
        $order = $order->toArray();
        if($order['pay_status'] != YesNoEnum::YES) {
            throw new \think\Exception('订单未付款,不允许发起整单退款');
        }

        if($order['order_status'] != OrderEnum::STATUS_WAIT_DELIVERY && $order['order_status'] != OrderEnum::STATUS_CLOSE) {
            // 订单已关闭的情况之一：用户完成支付完后但第三方未及时调用我方支付回调，有可能此时用户手动或后台手动取消订单了订单
            throw new \think\Exception('订单已发货,不允许发起整单退款');
        }

        $aferSale = AfterSale::where([
            ['order_id', '=', $order['id']],
            ['status', '=', AfterSaleEnum::STATUS_SUCCESS]
        ])->select()->toArray();
        if($aferSale) {
            throw new \think\Exception('该订单已售后成功, 不能重复发起售后');
        }

        $aferSale = AfterSale::where([
            ['order_id', '=', $order['id']],
            ['status', '=', AfterSaleEnum::STATUS_ING]
        ])->select()->toArray();
        if($aferSale) {
            throw new \think\Exception('该订单已在售后中，请耐心等待');
        }
    }

    /**
     * @notes 生成售后记录
     * @param $params
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function createAfterSale($params)
    {
        $order = Order::findOrEmpty($params['order_id'])->toArray();
        // 生成售后主表记录
        $data = [
            'sn' => generate_sn((new AfterSale()), 'sn'),
            'user_id' => $order['user_id'],
            'order_id' => $order['id'],
            'refund_reason' => AfterSaleLogEnum::getSenceDesc($params['scene']),
            'refund_remark' => '系统发起整单退款',
            'refund_type' => AfterSaleEnum::REFUND_TYPE_ORDER,
            'refund_method' => AfterSaleEnum::METHOD_ONLY_REFUND,
            'refund_way' => AfterSaleEnum::REFUND_WAYS_ORIGINAL,
            'refund_total_amount' => $order['order_amount'],
            'status' => AfterSaleEnum::STATUS_ING,
            'sub_status' => AfterSaleEnum::SUB_STATUS_SELLER_REFUND_ING,
            'refund_status' => AfterSaleEnum::NO_REFUND
        ];

        $afterSale = AfterSale::create($data);

        // 生成售后商品记录
        $orderGoods = OrderGoods::where('order_id', $order['id'])->select()->toArray();
        $data = [];
        foreach($orderGoods as $item) {
            $data[] = [
                'after_sale_id' => $afterSale->id,
                'order_goods_id' => $item['id'],
                'goods_id' => $item['goods_id'],
                'item_id' => $item['item_id'],
                'goods_price' => $item['goods_price'],
                'goods_num' => $item['goods_num'],
                'refund_amount' => $item['total_pay_price']
            ];
        }
        (new AfterSaleGoods())->saveAll($data);

        // 生成售后日志
        $msg = ',系统发起整单退款';
        switch($params['scene']) {
            case AfterSaleLogEnum::BUYER_CANCEL_ORDER:
                $content = AfterSaleLogEnum::getSenceDesc(AfterSaleLogEnum::BUYER_CANCEL_ORDER) . $msg;
                self::createAfterLog($afterSale->id, $content, null, AfterSaleLogEnum::ROLE_SYS);
                break;
            case AfterSaleLogEnum::SELLER_CANCEL_ORDER:
                $content = AfterSaleLogEnum::getSenceDesc(AfterSaleLogEnum::SELLER_CANCEL_ORDER) . $msg;
                self::createAfterLog($afterSale->id, $content, null, AfterSaleLogEnum::ROLE_SYS);
                break;
            case AfterSaleLogEnum::ORDER_CLOSE:
                $content = AfterSaleLogEnum::getSenceDesc(AfterSaleLogEnum::ORDER_CLOSE) . $msg;
                self::createAfterLog($afterSale->id, $content, null, AfterSaleLogEnum::ROLE_SYS);
                break;
        }

        // 整单退款
        RefundLogic::refund(AfterSaleEnum::REFUND_WAYS_ORIGINAL, $order, $afterSale->id, $order['order_amount']);
    }

    /**
     * @notes 生成售后日志
     * @param $type
     * @param $afterSaleId
     * @param $content
     * @param null $operatorId
     */
    public static function createAfterLog($afterSaleId, $content, $operatorId = null,$operatorRole = null)
    {
        $data = [
            'after_sale_id' => $afterSaleId,
            'content' => $content,
            'operator_id' => $operatorId,
            'operator_role' => $operatorRole
        ];

        AfterSaleLog::create($data);
    }

    /**
     * @notes 退还库存
     * @param $params
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public static function returnInventory($params)
    {
        $orderGoods = OrderGoods::where(['order_id' => $params['order_id']])->select()->toArray();

        foreach($orderGoods as $item) {
            $goods = Goods::findOrEmpty($item['goods_id']);
            if($goods->isEmpty()){
                continue;
            }
            $goodsItem = GoodsItem::findOrEmpty($item['item_id']);
            $goodsItem->stock = $goodsItem->stock + $item['goods_num'];
            $goodsItem->save();


            $goods->total_stock = $goods->total_stock + $item['goods_num'];
            $goods->save();
        }
    }

}