<?php

namespace app\common\repositories\user;

use app\common\dao\user\UserSignScoreDao;
use app\common\enum\user\UserSignScoreEnum;
use app\common\repositories\BaseRepository;
use app\common\repositories\store\order\StoreOrderRepository;
use app\entity\data\user\UserEntity;
use app\entity\data\user\UserSignScoreEntity;
use think\db\exception\DbException;
use think\exception\ValidateException;

class UserSignScoreRepository extends BaseRepository
{
    public function __construct(UserSignScoreDao $dao)
    {
        $this->dao = $dao;
    }

    public function create($data)
    {
        return $this->dao->create($data);
    }

    /**
     * @param int $id
     * @return UserSignScoreEntity
     */
    public function getUserSignScoreEntityById(int $id): UserSignScoreEntity
    {
        $entityList = $this->getUserSignScoreEntityListByIdList([$id]);
        $entity = array_shift($entityList);
        if ($entity instanceof UserSignScoreEntity) {
            return $entity;
        } else {
            /** @var UserSignScoreEntity */
            return UserSignScoreEntity::newInstance();
        }
    }

    /**
     * @param array $idList
     * @return UserSignScoreEntity[]
     */
    public function getUserSignScoreEntityListByIdList(array $idList): array
    {
        return $this->dao->getUserSignScoreEntityListByIdList($idList);
    }

    /**
     * @param string $orderType
     * @param array $orderIdList
     * @return UserSignScoreEntity[]
     */
    public function getUserSignScoreEntityListByOrderIdListAndPending(string $orderType, array $orderIdList): array
    {
        return $this->dao->getUserSignScoreEntityListByOrderIdListAndPending($orderType, $orderIdList);
    }

    /**
     * 写入积分记录
     * @param UserSignScoreEntity $userSignScoreEntity
     * @return UserSignScoreEntity
     */
    public function createByEntity(UserSignScoreEntity $userSignScoreEntity): UserSignScoreEntity
    {
        $result = $this->create($userSignScoreEntity->toUnderlineArray())->toArray();
        /** @var UserSignScoreEntity $entity */
        $entity = UserSignScoreEntity::newInstance($result);
        return $entity;
    }

    /**
     * 添加 积分记录
     * @param int $uid
     * @param int $sourceType
     * @param int $type
     * @param float $number
     * @param string $mark
     * @param string $orderType
     * @param string $orderId
     * @return UserSignScoreEntity
     */
    public function addUserSingScore(int $uid, int $sourceType, int $type, float $number, string $mark = '', string $orderType = '', string $orderId = ''): UserSignScoreEntity
    {

        if (!empty($orderType)) {
            if (!empty($orderId)) {
                if ($orderType == UserSignScoreEnum::ORDER_TYPE['Platform']['code']) {
                    /** @var StoreOrderRepository $storeOrderRepository */
                    $storeOrderRepository = app()->make(StoreOrderRepository::class);
                    $storeOrderEntity = $storeOrderRepository->getStoreOrderEntityByOrderId((int)$orderId);
                    if (empty($storeOrderEntity->getOrderId())) {
                        throw new ValidateException('未查询到订单信息');
                    }
                }
            }
        }

        /** @var UserSignScoreEntity $userSignScoreEntity */
        $userSignScoreEntity = UserSignScoreEntity::newInstance();
        $userSignScoreEntity->setUid($uid)
            ->setSourceType($sourceType)
            ->setPm($type)
            ->setRewardSocre($number)
            ->setMark($mark)
            ->setOrderType($orderType)
            ->setOrderId($orderId)
            ->setAddtime(time())
            ->setStatus(UserSignScoreEnum::STATUS['Pending']['code']);

        return $this->createByEntity($userSignScoreEntity);
    }

    /**
     * 将 积分 记录设置为生效状态 并对用户的 积分 字段进行增减
     * @param int $id
     * @return int
     */
    public function execute(int $id): int
    {
        $result = $this->executeByIdList([$id]);
        return array_shift($result);
    }

    /**
     * 将 积分 记录设置为生效状态 并对用户的 积分 字段进行增减
     * @param array $idList
     * @return array
     */
    public function executeByIdList(array $idList): array
    {
        $userSignScoreEntityList = $this->getUserSignScoreEntityListByIdList($idList);
        $userIdList = [];

        // 忽略 已经生效的 记录
        $userSignScoreEntityList = array_filter($userSignScoreEntityList, function ($entity) use (&$userIdList) {
            // 积分数据不为空 用户不为空 状态属于待结算 并且结算字段为空
            if ((!empty($entity->getId()) && !empty($entity->getUid()) && ($entity->getStatus() == UserSignScoreEnum::STATUS['Pending']['code']) && empty($entity->getSettlementTime()))) {
                $userIdList[] = $entity->getUid();
                return true;
            }
            return false;
        });

        if (!empty($userSignScoreEntityList)) {
            // 获取用户 映射信息
            /** @var UserRepository $userRepository */
            $userRepository = app()->make(UserRepository::class);
            /** @var UserEntity[] $userEntityMapByUid */
            $userEntityMapByUid = [];
            if (!empty($userIdList)) {
                $userEntityMapByUid = $userRepository->getUserEntityMapByUidList($userIdList);
            }

            /** @var UserEntity[] $updateUserEntityList */
            $updateUserEntityList = [];
            /** @var UserSignScoreEntity[] $updateUserScoreEntityList */
            $updateUserScoreEntityList = [];
            foreach ($userSignScoreEntityList as $userSignScoreEntity) {
                // if (empty($userSignScoreEntity->getId()) || empty($userSignScoreEntity->getUid())) {
                //     throw new ValidateException('无效的积分记录');
                // }
                // if ($userSignScoreEntity->getStatus() == UserSignScoreEnum::STATUS['Invalid']['code']) {
                //     throw new ValidateException('该积分记录已失效');
                // }
                // if (!empty($userSignScoreEntity->getSettlementTime()) || $userSignScoreEntity->getStatus() == UserSignScoreEnum::STATUS['Valid']['code']) {
                //     throw new ValidateException('该积分记录已更新，请勿重复操作');
                // }

                $userEntity = $userEntityMapByUid[$userSignScoreEntity->getUid()];
                if (empty($userEntity) || empty($userEntity->getUid())) {
                    throw new ValidateException("未查询到用户信息(scoreId:{$userSignScoreEntity->getId()})");
                }

                // 组建 更新 用户信息
                if (isset($updateUserEntityList[$userEntity->getUid()])) {
                    $updateUserEntity = $updateUserEntityList[$userEntity->getUid()];
                } else {
                    /** @var UserEntity $updateUserEntity */
                    $updateUserEntity = UserEntity::newInstance();
                    $updateUserEntity
                        ->setUid($userEntity->getUid())
                        ->setScore($userEntity->getScore());

                }
                // 组建 账单 记录
                if (isset($updateUserScoreEntityList[$userSignScoreEntity->getId()])) {
                    $updateUserSignScoreEntity = $updateUserScoreEntityList[$userSignScoreEntity->getId()];
                } else {
                    /** @var UserSignScoreEntity $updateUserSignScoreEntity */
                    $updateUserSignScoreEntity = UserSignScoreEntity::newInstance();
                    // 更新 账单记录 状态
                    $updateUserSignScoreEntity
                        ->setId($userSignScoreEntity->getId())
                        ->setStatus(UserSignScoreEnum::STATUS['Valid']['code'])
                        ->setSettlementTime(time());
                }

                if ($userSignScoreEntity->getPm() == UserSignScoreEnum::PM['Expend']['code']) {
                    // 支出
                    $updateUserEntity->setScore(bcsub($updateUserEntity->getScore(), $userSignScoreEntity->getRewardSocre(), 2));
                    if ($updateUserEntity->getScore() < 0.00) {
                        throw new ValidateException('用户积分不足');
                    }
                } else {
                    $updateUserEntity->setScore(bcadd($updateUserEntity->getScore(), $userSignScoreEntity->getRewardSocre(), 2));
                }
                $updateUserSignScoreEntity->setSurplus($updateUserEntity->getScore());

                $updateUserEntityList[$userSignScoreEntity->getUid()] = $updateUserEntity;
                $updateUserScoreEntityList[$userSignScoreEntity->getId()] = $updateUserSignScoreEntity;
            }
            try {
                if (!empty($updateUserEntityList)) {
                    $userRepository->batchUpdateUserDataByDataList(
                        array_map(function (UserEntity $updateUserEntity) {
                            return $updateUserEntity->toUnderlineArray();
                        }, $updateUserEntityList)
                    );
                }

                if (!empty($updateUserScoreEntityList)) {
                    $this->batchUpdateUserSignScoreDataByDataList(
                        array_map(function (UserSignScoreEntity $updateUserSignScoreEntity) {
                            return $updateUserSignScoreEntity->toUnderlineArray();
                        }, $updateUserScoreEntityList)
                    );
                }
            } catch (\Exception $e) {
                throw new ValidateException('用户积分结算失败');
            }
        }
        return $idList;
    }

    /**
     * @param $dataList
     * @return array
     */
    public function batchUpdateUserSignScoreDataByDataList($dataList): array
    {
        return $this->dao->saveAll($dataList);
    }
}