<?php
/**
 *
 * @author：llbjj
 * @DateTime：2022/5/4 13:42
 * @Description：登录
 *
 */

namespace Application\Controller;

use Application\Common\Container;
use Application\Common\Crypt;
use Application\Common\RedisEnum;
use Application\Form\FieldForm;
use Application\Mvc\Controller\Plugins\RenderApiJson;
use Application\Service\Extension\ErrorHandler;
use Application\Service\Extension\Helper\ValidatorHelper;
use Application\Service\Extension\Identity\Identity;
use Application\Service\Extension\Laminas;
use Application\Form\LoginForm;
use Application\Common\StatusCode;
use Application\Service\Extension\Helper\StringHelper;
//use Application\Service\Extension\Model\XmlModel;
use Application\Service\Extension\Queue\jobs\SyncPatientFormJob;
use Application\Service\Extension\Queue\jobs\SyncPatientJob;
use Application\Service\Extension\Queue\QueueApplication;
//use Application\Service\Extension\Queue\QueueMessage;
//use Application\Service\Extension\Queue\job\TestQueue;
use Application\Service\Extension\Sms\SmsRateLimitException;
use Application\Service\Extension\Validator\ValidatorApplication;
use Application\Service\Extension\ValidatorV2\Validator;
use Application\Service\Extension\Xml\FormContentXmlGenerator;
use Application\Service\Extension\Xml\PatientXmlGenerator;
use Application\Service\Extension\Xml\XmlBuilder;
//use Application\Service\Extension\XmlGenerate;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use EasyWeChat\Kernel\Messages\Text;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Laminas\Db\Sql\Where;
use Laminas\Http\Client;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\Mvc\Exception\InvalidArgumentException;
use Laminas\View\Model\JsonModel;
use Laminas\View\Model\ViewModel;
use Overtrue\Socialite\Exceptions\AuthorizeFailedException;
use Overtrue\Socialite\User;

use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;

/**
 * Class LoginController
 * @package Application\Controller
 * @method Container LocalService()
 * @method RenderApiJson RenderApiJson()
 */
class WechatController extends AbstractActionController
{
    /**
     * 微信回调入口
     * @url xxx.com/wechat/entry
     * @throws InvalidConfigException
     * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \ReflectionException
     */
    public function entryAction()
    {
        if (isset($_GET["echostr"])) {
            $echoStr = $_GET["echostr"];//从微信用户端获取一个随机字符赋予变量echostr
            //valid signature , option访问地61行的checkSignature签名验证方法，如果签名一致，输出变量    echostr，完整验证配置接口的操作
            if($this->checkSignature()){
                echo $echoStr;
                exit;
            }
        } else {
            $app = Laminas::$serviceManager->wechat->getApp();
            $app->server->push(function($message) {
                return $this->LocalService()->wechat->getMessage()->handle($message);
            });

            $response = $app->server->serve();
            $response->send();
            die;
        }
    }

    /**
     * 微信验签
     * @return bool
     */
    private function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $token = '66668888';
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );

        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 受试者绑定界面
     * @url xxx.com/wechat/bind
     * @return \Laminas\Http\Response|ViewModel
     */
    public function bindAction()
    {
        if (!$_GET['code']) {
            $redirectUrl = $this->LocalService()->wechat->getApp()
                ->oauth
                ->scopes(['snsapi_base'])->with(['forceSnapShot' => true])
                ->redirect("{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}/wechat/bind");
            return $this->redirect()->toUrl($redirectUrl);
        }
        $view = new ViewModel();
        $view->setTemplate('application/wechat/bind');
        $this->layout('layout/wechat');
        $view->setVariables([
            'code' => $_GET['code'],
            'host' => "{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}"
        ]);

        return $view;
    }

    /**
     * 获取绑定微信短信验证码
     * @url xxx.com/wechat/bind-captcha
     * @return JsonModel
     * @throws GuzzleException
     */
    public function bindCaptchaAction(): JsonModel
    {
        $mobile = $this->params()->fromPost('mobile');
        $code = $this->params()->fromPost('code');
        $api = [
//            'http://lzy.kingdone.com/common/patient-mobile',
            'https://www.5-mc.cn/common/patient-mobile',
            'https://www.scitrials.cn/common/patient-mobile',
        ];

        $hasMobile = false;
        $arr = [];
        foreach ($api as $item) {
            $sign = md5($mobile . CommonController::SECRET_KEY);
            $client = new \GuzzleHttp\Client();
            $content = $client->get("{$item}?sign={$sign}&mobile={$mobile}")->getBody()->getContents();

            if ($content === '1') {
                $hasMobile = true;
                $arr[$code][] = $item;
            } elseif ($content === '-1') { // 已经绑定
                return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, "当前手机号码无法绑定。请先解绑关联关系。");
            }
        }

        if (!$hasMobile) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, "当前手机号码无法绑定。请确定手机号是否正确。");
        }

        $captcha = mt_rand(1000, 9999);
        Laminas::$serviceManager->redisExtend->getRedisInstance()->setex("bind:{$mobile}:{$captcha}:{$code}", 3600, json_encode($arr));
        $this->LocalService()->sms->send($mobile, $captcha);
        return $this->RenderApiJson()->Success();
    }

    /**
     * 绑定
     * @return JsonModel
     * @throws GuzzleException
     * @throws InvalidConfigException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
     */
    public function bindSubmitAction(): JsonModel
    {
        $mobile = $this->params()->fromPost('mobile');
        $captcha = $this->params()->fromPost('captcha');
        $code = $this->params()->fromPost('code', '');
        $captchaKey = "bind:{$mobile}:{$captcha}:{$code}";
        $captchaCache = Laminas::$serviceManager->redisExtend->getRedisInstance()->get("bind:{$mobile}:{$captcha}:{$code}");
        $openid = Laminas::$serviceManager->wechat->getApp()->oauth->userFromCode($code)->getId();
        $user = $this->LocalService()->wechat->getApp()->user->get($openid);

        if ($user && isset($user['errmsg'])) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, "绑定失败。请重进页面重新进行绑定。");
        }

        if ($user['subscribe'] != 1) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, "请关注公众号。");
        }

        if (!$captchaCache) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, "验证码有误。");
        }

        foreach (StringHelper::jsonDecode($captchaCache) as $code => $urlArr) {
            foreach ($urlArr as $item) {
                $sign = md5($mobile . CommonController::SECRET_KEY);
                $client = new \GuzzleHttp\Client();
                $client->get("{$item}?sign={$sign}&mobile={$mobile}&openid={$openid}")->getBody()->getContents();
            }
        }

        $this->LocalService()->wechat->getApp()->customer_service->message(new Text("您在" . date('Y-m-d H:i:s') . '绑定成功。'))->to($openid)->send();

        Laminas::$serviceManager->redisExtend->getRedisInstance()->del($captchaKey);
        return $this->RenderApiJson()->Success();
    }
}