<?php

namespace app\common\repositories\user;

use app\common\dao\user\UserSignFugouDao;
use app\common\enum\user\UserSignFugouEnum;
use app\common\repositories\BaseRepository;
use app\common\repositories\store\order\StoreOrderRepository;
use app\entity\data\user\UserEntity;
use app\entity\data\user\UserSignFugouEntity;
use think\db\exception\DbException;
use think\exception\ValidateException;

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

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

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

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

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

    /**
     * 写入 复购金 记录
     * @param UserSignFugouEntity $userSignFugouEntity
     * @return UserSignFugouEntity
     */
    public function createByEntity(UserSignFugouEntity $userSignFugouEntity): UserSignFugouEntity
    {
        $result = $this->dao->create($userSignFugouEntity->toUnderlineArray())->toArray();
        /** @var UserSignFugouEntity $entity */
        $entity = UserSignFugouEntity::newInstance($result);
        return $entity;
    }

    /**
     * 添加 复购金记录
     * @param int $uid
     * @param int $type
     * @param float $number
     * @param int $commissionType
     * @param string $mark
     * @param string $orderType
     * @param string $orderId
     * @return UserSignFugouEntity
     */
    public function addUserSingFugou(int $uid, int $type, float $number, int $commissionType, string $mark = '', string $orderType = '', string $orderId = ''): UserSignFugouEntity
    {
        if (!empty($orderType)) {
            if (!empty($orderId)) {
                if ($orderType == UserSignFugouEnum::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 UserSignFugouEntity $userSignFugouEntity */
        $userSignFugouEntity = UserSignFugouEntity::newInstance();
        $userSignFugouEntity->setUid($uid)
            ->setType($type)
            ->setNumber($number)
            ->setCommissionType($commissionType)
            ->setMark($mark)
            ->setOrderType($orderType)
            ->setOrderId($orderId)
            ->setAddtime(time())
            ->setStatus(UserSignFugouEnum::STATUS['Pending']['code']);

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

    /**
     * 将 复购 记录设置为生效状态 并对用户的 复购 字段进行增减
     * @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
    {
        $userSignFugouEntityList = $this->getUserSignFugouEntityListByIdList($idList);
        $userIdList = [];

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

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

            /** @var UserEntity[] $updateUserEntityList */
            $updateUserEntityList = [];
            /** @var UserSignFugouEntity[] $updateUserFugouEntityList */
            $updateUserFugouEntityList = [];
            foreach ($userSignFugouEntityList as $userSignFugouEntity) {

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

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

                }
                // 组建 账单 记录
                if (isset($updateUserFugouEntityList[$userSignFugouEntity->getId()])) {
                    $updateUserSignFugouEntity = $updateUserFugouEntityList[$userSignFugouEntity->getId()];
                } else {
                    /** @var UserSignFugouEntity $updateUserSignFugouEntity */
                    $updateUserSignFugouEntity = UserSignFugouEntity::newInstance();
                    // 更新 账单记录 状态
                    $updateUserSignFugouEntity
                        ->setId($userSignFugouEntity->getId())
                        ->setStatus(UserSignFugouEnum::STATUS['Valid']['code'])
                        ->setSettlementTime(date('Y-m-d H:i:s'));
                }

                if ($userSignFugouEntity->getType() == UserSignFugouEnum::TYPE['Consume']['code']) {
                    // 支出
                    $updateUserEntity->setFugou(bcsub($updateUserEntity->getFugou(), $userSignFugouEntity->getNumber(), 2));
                    if ($updateUserEntity->getFugou() < 0.00) {
                        throw new ValidateException('用户复购金不足');
                    }
                } else {
                    $updateUserEntity->setFugou(bcadd($updateUserEntity->getFugou(), $userSignFugouEntity->getNumber(), 2));
                }
                $updateUserSignFugouEntity->setSurplus($updateUserEntity->getFugou());

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

                if (!empty($updateUserFugouEntityList)) {
                    $this->batchUpdateUserSignFugouDataByDataList(
                        array_map(function (UserSignFugouEntity $updateUserSignFugouEntity) {
                            return $updateUserSignFugouEntity->toUnderlineArray();
                        }, $updateUserFugouEntityList)
                    );
                }
            } catch (\Exception $e) {
                throw new ValidateException('用户复购金结算失败');
            }
        }
        return $idList;
    }

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