<?php

use Api\PhpServices\Idgen\Idgen;
use Api\PhpUtils\Log\FileLog;
use App\Base\Cli;
use App\Models\marketing\mysql\ColonelDistributorColonel;
use App\Models\marketing\mysql\ColonelDistributorConfig;
use App\Models\marketing\mysql\ColonelDistributorInviteOrderNum;
use App\Models\marketing\mysql\ColonelDistributorPayInfo;
use App\Exception\custom\InterfaceException;
use Api\PhpUtils\Http\HttpUtil;
use App\Models\user\mysql\UserWechatBind;

/**
 * php public/cli.php colonelorder index
 */
class ColonelorderController extends Cli
{
    const DEFAULT_USER_BATCH_SIZE = 100;

    public $today;
    public $yesterday;
    public $colonelConfig;
    public $colonelConfigList;

    public function init()
    {
        parent::init();
        $this->today         = date("Y-m-d");
        $this->yesterday     = date("Y-m-d", strtotime("-1 day"));
        $this->colonelConfig = $this->getColonelConfig($this->yesterday);
        if (!empty($this->colonelConfig)) {
            $this->colonelConfigList = json_decode($this->colonelConfig['data'], true);
        }
    }

    public function indexAction()
    {
        $userIdList = $this->getColonelUserIds();
        if (empty($userIdList) || empty($this->colonelConfigList)) {
            return true;
        }
        $userIdList = array_chunk($userIdList, self::DEFAULT_USER_BATCH_SIZE);
        $colonelPayInfoData = [];
        foreach ($userIdList as $userIds) {
            $batchPayInfoData   = [];
            // 完成目标单数
            $batchPayInfoData[] = $this->getInviteOrderData($userIds);
            // 邀请新用户奖励
            $batchPayInfoData[] = $this->getInviteNewUserData($userIds);
            $colonelPayInfoData = array_merge($colonelPayInfoData, $batchPayInfoData);
        }
        return $this->handleSavePayInfo($colonelPayInfoData);
    }

    /**
     * 保存奖励信息
     * @param $yesterday
     * @return true
     */
    public function handleSavePayInfo($colonelPayInfoData)
    {
        if (!empty($colonelPayInfoData)) {
            $data = $this->addIdgenId($colonelPayInfoData);
            try {
                ColonelDistributorPayInfo::beginTransaction();
                if (!$this->addColonelDistributorPayInfo($data)) {
                    throw new \Exception(sprintf("写入错误参数 %s", json_encode($data)));
                }
                if (!ColonelDistributorPayInfo::commit()) {
                    throw new \Exception(sprintf("事务提交失败 %s", json_encode($data)));
                }
            } catch (\Exception $e) {
                ColonelDistributorPayInfo::rollback();
                FileLog::info("add_colonel_distributor_pay_info", $e->getMessage());
            }
        }
        return true;
    }

    /**
     * 获取新用户奖励
     * @param $yesterday
     * @return array
     */
    public function getInviteNewUserData($userIds)
    {
        $inviteNewUserList = $this->getInviteNewUserList($userIds, $this->today);
        $inviteOrderData   = [];
        if (!empty($inviteNewUserList)) {
            $userNickList = $this->getUserList(array_column($inviteNewUserList, "user_id"));
            foreach ($inviteNewUserList as $newUser) {
                $payInfo = [
                    "colonel_user_id" => $newUser["inviter_user_id"],
                    "date" => $this->yesterday,
                    "type" => ColonelDistributorPayInfo::TYPE_NEW_USER,
                    "reward" => 3 * 100,
                    "finish_num" => 1,
                    "invite_user_id" => $newUser["user_id"],
                    "invite_user_nick" => empty($userNickList[$newUser["user_id"]]["user_nick"]) ? "" : $userNickList[$newUser["user_id"]]["user_nick"],
                ];
                $inviteOrderData[] = $payInfo;
            }
        }
        return $inviteOrderData;
    }

    /**
     * 获取完成目标单数奖励
     * @param $yesterday
     * @return array
     */
    public function getInviteOrderData($userIds)
    {
        //完成目标单数
        $inviteOrderNumList = $this->getInviteOrderNum($userIds, $this->yesterday, $this->today);
        $inviteOrderData = [];
        foreach ($inviteOrderNumList as $orderNum) {
            foreach ($this->colonelConfigList as $config) {
                if (!empty($orderNum["num"]) && $orderNum["num"] >= $config["assess_order_num"]) {
                    $payInfo = [
                        "colonel_user_id" => $orderNum["colonel_user_id"],
                        "date" => $this->yesterday,
                        "type" => ColonelDistributorPayInfo::TYPE_FINISH_TARGET,
                        "reward" => $config["reward_amount"] * 100,
                        "finish_num" => $config["assess_order_num"],
                        "invite_user_id" => 0,
                        "invite_user_nick" => "",
                    ];
                    $inviteOrderData[] = $payInfo;
                }
            }
        }
        return $inviteOrderData;
    }

    /**
     * 团长任务配置
     * @param $yesterday
     * @return \Api\PhpUtils\Mysql\MysqlBase
     */
    public function getColonelConfig($yesterday)
    {
        $type = empty($params["type"]) ? ColonelDistributorConfig::TYPE_COLONEL : $params["type"];
        $config = ColonelDistributorConfig::getRecord(["date" => $yesterday, "type" => $type]);
        if (empty($config)) {
            $config = ColonelDistributorConfig::getRecord([
                "date[<=]" => $yesterday,
                "ORDER" => ["date" => "DESC"],
                "LIMIT" => 1
            ]);
        }
        return $config;
    }

    /**
     * 团长user_id
     * @return array
     */
    public function getColonelUserIds()
    {
        $colonelRes = ColonelDistributorColonel::select(["user_id"], ["LIMIT" => 10000000]);
        $userIds = [];
        if (!empty($colonelRes)) {
            $userIds = array_column($colonelRes, "user_id");
        }
        return $userIds;
    }

    /**
     * 获取order num
     * @param $colonelUserIds
     * @param $startTime
     * @param $endTime
     * @return \Api\PhpUtils\Mysql\MysqlBase
     */
    public function getInviteOrderNum($colonelUserIds, $startTime, $endTime)
    {
        return ColonelDistributorInviteOrderNum::select(
            ["colonel_user_id", "num", "date"],
            [
                "colonel_user_id" => $colonelUserIds,
                "date[>=]" => $startTime,
                "date[<=]" => $endTime,
            ],
            []
        );
    }

    /**
     * 获取有效新用户信息
     * @param $userIds
     * @param $date
     * @return array|mixed
     * @throws InterfaceException
     */
    public function getInviteNewUserList($userIds, $date)
    {
        $url = config('interface', 'coupon.background.wx_invite_relation_list_by_user_ids');
        if (empty($url)) {
            throw new InterfaceException(['cus' => 0]);
        }

        $res = HttpUtil::get($url, ["user_ids" => $userIds, "date" => $date]);
        if (!empty($res["response"]["result"])) {
            $res = array_column($res["response"]["result"], null, "user_id");
            return array_values($res);
        }
        return [];
    }

    /**
     * 给数据整理 colonel_distributor_pay_info_id
     * @param $data
     * @param string $type
     * @return mixed
     */
    public function addIdgenId($data, $type = "goods")
    {
        $count = count($data);
        $res = Idgen::get(appConfig('idgen.partner'), appConfig('idgen.key'), [], [[
            "type" => $type,
            'number' => 00,
            "count" => $count]]);
        $ids = $res['id_datetime'][$type] ?? [];
        foreach ($data as $key => $item) {
            $data[$key]["colonel_distributor_pay_info_id"] = $ids[$key];
        }
        return $data;
    }

    /**
     * 用户信息，获取昵称
     * @param $userIds
     * @return \Api\PhpUtils\Mysql\MysqlBase|array
     */
    public function getUserList($userIds)
    {
        $list = UserWechatBind::select(["user_id", "user_nick"], ["user_id" => $userIds], []);
        if (!empty($list)) {
            $list = array_column($list, null, "user_id");
        }
        return $list;
    }

    /**
     * 写入数据
     * @param $data
     * @return \Api\PhpUtils\Mysql\MysqlBase
     */
    public function addColonelDistributorPayInfo($data)
    {
        return ColonelDistributorPayInfo::save($data);
    }
}
