<?php
declare (strict_types=1);

namespace app\common\service\server;

use app\api\model\dealer\User as DealerUserModel;
use app\api\model\Server\ServerOrder;
use app\api\model\UserCoupon;
use app\api\service\User as UserService;
use app\common\enum\coupon\CouponType as CouponTypeEnum;
use app\common\enum\coupon\TypeCase;
use app\common\enum\dealer\DealerUserEnum;
use app\common\enum\order\PayStatus;
use app\common\enum\ServerEnum;
use app\common\library\helper;
use app\common\model\server\Server;
use app\common\model\UserCoupon as UserCouponModel;
use app\common\service\BaseService;
use app\common\service\Order as OrderService;
use app\common\service\order\Refund as RefundService;
use app\store\model\dealer\User as UserModel;
use cores\exception\BaseException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class Order extends BaseService
{
    /**
     * 订单结算的规则
     * @var array
     */
    private array $checkoutRule = [
        'isUserGrade' => true,    // 会员等级折扣
        'isCoupon' => true,        // 优惠券抵扣
        'isUsePoints' => true,        // 是否使用积分抵扣
        'isDealer' => true,        // 是否开启分销
    ];

    private array $serverInfo;

    private int $serverId;
    private int $couponId;

    /**
     * 生成订单号
     * @return string
     */
    private function orderNo(): string
    {
        return OrderService::createOrderNo();
    }

    /**
     * @notes:用户取消订单
     * @param array $order
     * @return bool
     * @throws BaseException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @author: wanghousheng
     */
    public static function cancelOrder(array $order): bool
    {
        //未完成 未取消
        if (!empty($order['order_status']) && self::checkCancel($order)) {
            if (!empty($order['coupon_id'])) {
                // 回退用户优惠券
                $order['coupon_id'] > 0 && UserCouponModel::setIsUse($order['coupon_id'], false);
            }
            //判断是否已支付
            if ($order['pay_status'] == PayStatus::SUCCESS) {
                if (!(new RefundService)->handle($order)) {
                    try {
                        throwError('执行订单退款失败');
                    } catch (BaseException $e) {
                        return false;
                    }
                }
            }
            //更新订单状态
            $model = new \app\common\model\server\Order;
            $model->where(['order_id' => $order['order_id']])->save(['order_status' => ServerEnum::CANCELLED]);
            return true;
        }
        return false;
    }

    /**
     * @notes:是否可以取消
     * @param $order
     * @return bool
     * @author: wanghousheng
     */
    public static function checkCancel($order): bool
    {

        if (!empty($order['order_status']) && !in_array($order['order_status'], [ServerEnum::COMPLETED, ServerEnum::CANCELLED])) {
            return true;
        }
        return false;
    }

    /**
     * @notes:是否可以派单
     * @param $order
     * @return bool
     * @throws BaseException
     * @author: wanghousheng
     */
    public static function checkDispatch($order): bool
    {
        if (!empty($order) && $order['order_status'] == ServerEnum::APPLYDISPATCH && UserService::isStore()) {
            return true;
        }
        return false;
    }

    /**
     * @notes:是否可以完成
     * @param $order
     * @return bool
     * @throws BaseException
     * @author: wanghousheng
     */
    public static function checkSuccess($order): bool
    {
        if (!UserService::isDealerEngineer() || !UserService::isStore()) {
            return false;
        }
        if (!empty($order) && $order['order_status'] == ServerEnum::APPLYSERVER) {
            return true;
        }
        return false;
    }

    /**
     * @notes:是否可以支付
     * @param $order
     * @return bool
     * @throws BaseException
     * @author: wanghousheng
     */
    public static function checkPay($order): bool
    {
        $userId = UserService::getCurrentLoginUserId();
        if (!empty($order) && $order['pay_status'] == PayStatus::PENDING && $order['user_id'] == $userId && $order['order_status'] == ServerEnum::APPLYPAY) {
            return true;
        }
        return false;
    }

    /**
     * @notes:派单
     * @param array $order
     * @param int $dealerId
     * @return bool
     * @author: wanghousheng
     */
    public static function dispatchOrders(array $order, int $dealerId): bool
    {
        //判断该订单是否可以指派
        if (!empty($order) && $order['order_status'] == ServerEnum::APPLYDISPATCH) {
            //判断指派人员是否是分销工程师
            $dealerInfo = DealerUserModel::detail($dealerId, []);
            if (!empty($dealerInfo)) {
                $dealerInfo = $dealerInfo->toArray();
                if ($dealerInfo['type'] == DealerUserEnum::ENGINEER) {
                    $model = new \app\common\model\server\Order;
                    $up['dealer_id'] = $dealerId;
                    $up['order_status'] = ServerEnum::APPLYSERVER;
                    $model->where(['order_id' => $order['order_id']])->save($up);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @notes:生成订单
     * @param array $params
     * @param int $couponId
     * @return array
     * @throws BaseException
     * @throws DbException
     * @author: wanghousheng
     */
    public function createOrder(array $params, int $couponId): array
    {
        $userId = UserService::getCurrentLoginUserId();
        $data = $this->onCheck($params['server_id'], $couponId);
        // 设置优惠券使用状态
        $couponId > 0 && UserCoupon::setIsUse($couponId);
        //封装数据
        $order_data = [
            'order_no' => $this->orderNo(),
            'server_name' => $this->serverInfo['server_name'],
            'server_image_id' => $this->serverInfo['image_id'],
            'total_price' => $this->serverInfo['server_price'],
            'store_id' => $this->storeId,
            'user_id' => $userId,
            'coupon_id' => $data['coupon_id'],
            'coupon_money' => $data['coupon_money'],
            'pay_price' => $data['pay_price'],
            'create_time' => time(),
            'update_time' => time(),
        ];
        $order_data = array_merge($order_data, $params);
        $model = new ServerOrder();
        $order_id = $model->insertGetId($order_data);
        if ($order_id) {
            return ['order_no' => $order_data['order_no'], 'order_id' => $order_id];
        }
        return [];
    }

    /**
     * @notes:订单确认-结算台
     * @param int $serverId
     * @param int $couponId
     * @return array
     * @throws BaseException
     * @throws DbException
     * @author: wanghousheng
     */
    public function onCheck(int $serverId, int $couponId): array
    {
        $this->serverId = $serverId;
        $this->couponId = $couponId;
        return $this->checkOut();
    }

    /**
     * @notes:订单结算台
     * @return array
     * @throws BaseException
     * @throws DbException
     * @author: wanghousheng
     */
    private function checkOut(): array
    {
        $info = Server::detail(['server_id' => $this->serverId, 'status' => 1], ['image', 'category']);
        if (empty($info)) {
            throwError('未找到服务信息');
        }
        $this->serverInfo = $info->toArray();
        $couponList = $this->getUserCouponList();
        $couponMoney = 0;
        if ($couponList && $this->couponId) {
            $couponMoney = $this->getCouponMoney($this->couponId, $couponList);
        }
        return [
            'info' => $this->serverInfo,
            'server_id' => $this->serverId,
            'coupon_list' => $couponList,
            'coupon_money' => $couponMoney,
            'coupon_id' => $this->couponId,
            'pay_price' => helper::number2($this->serverInfo['server_price'] - $couponMoney),
        ];
    }

    /**
     * 当前用户可用的优惠券列表
     * @return array
     * @throws DbException|BaseException
     */
    private function getUserCouponList(): array
    {
        // 是否开启优惠券折扣
        if (!$this->checkoutRule['isCoupon']) {
            return [];
        }
        $userId = UserService::getCurrentLoginUserId();
        // 当前用户可用的优惠券列表
        $couponList = UserCoupon::getUserCouponList($userId, (float)$this->serverInfo['server_price'], TypeCase::SERVER);
        // 判断当前优惠券是否满足订单使用条件 (优惠券适用范围)
        return UserCoupon::couponListApplyRangeServer($couponList, [$this->serverId]);
    }

    /**
     * 查找指定的优惠券信息
     * @param array $couponList 优惠券列表
     * @return false|mixed
     */
    private function getCouponInfo(int $userCouponId, array $couponList)
    {
        return helper::getArrayItemByColumn($couponList, 'user_coupon_id', $userCouponId);
    }

    /**
     * @notes:获取优惠金额
     * @param int $userCouponId
     * @param array $couponList
     * @return float|int|mixed
     * @author: wanghousheng
     */
    private function getCouponMoney(int $userCouponId, array $couponList)
    {
        // 获取优惠券信息
        $couponInfo = $this->getCouponInfo($userCouponId, $couponList);
        $reducedMoney = $this->serverInfo['server_price'];
        // 计算打折金额
        if ($couponInfo['coupon_type'] == CouponTypeEnum::DISCOUNT) {
            $reducePrice = $reducedMoney - ($reducedMoney * ($couponInfo['discount'] / 10));
        } else {
            $reducePrice = $couponInfo['reduce_price'];
        }
        $reducePrice = helper::number2($reducePrice);
        // 优惠券最大允许抵扣到一分钱,所以此处判断抵扣金额大于等于订单金额时,减去一分钱
        return ($reducePrice >= $reducedMoney) ? $reducedMoney - 1 : $reducePrice;
    }

    /**
     * @notes:用户取消订单
     * @param int $orderId
     * @return bool
     * @throws BaseException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @author: wanghousheng
     */
    public static function userCancelOrder(int $orderId): bool
    {
        $userId = UserService::getCurrentLoginUserId();
        $where['order_id'] = $orderId;
        if (UserService::isDealerMember()) {
            return false;
        }
        if (UserService::isPlusMember() || UserService::isNormalMember()) {
            $where['user_id'] = $userId;
        }
        $orderInfo = ServerOrder::detail($where);
        if ($orderInfo->isEmpty()) {
            throwError('订单信息不存在');
        }
        return self::cancelOrder($orderInfo->toArray());
    }

    /**
     * @notes:派单
     * @param int $orderId
     * @param int $dealerId
     * @return bool
     * @throws BaseException
     * @author: wanghousheng
     */
    public static function userDispatchOrders(int $orderId, int $dealerId): bool
    {
        if (!UserService::isStore()) {
            return false;
        }
        $orderInfo = ServerOrder::detail(['order_id' => $orderId]);
        if ($orderInfo->isEmpty()) {
            throwError('订单信息不存在');
        }
        return self::dispatchOrders($orderInfo->toArray(), $dealerId);
    }

    /**
     * @notes:分销商工程师-派单人员列表
     * @return array
     * @throws BaseException
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @author: wanghousheng
     */
    public static function getEngineer(): array
    {
        if (UserService::isStore()) {
            $list = UserModel::getEngineer();
            if (!$list->isEmpty()) {
                return $list->toArray();
            }
        }
        return [];
    }

}