<?php

namespace Modules\User\Http\Controllers\Api\Socialite;

use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jason\Api\Api;
use Modules\User\Events\UserLoginSuccess;
use Modules\User\Facades\Sms;
use Modules\User\Http\Requests\WechatMiniRequest;
use Modules\User\Models\User;
use Modules\User\Models\UserSubscribe;
use Modules\User\Models\UserWechat;
use Modules\User\Traits\WechatTrait;

class WeChatController extends Controller
{
    use WechatTrait;

    protected array $config = [];

    /**
     * Notes   : APP 登录
     *
     * @Date   : 2021/6/10 3:40 下午
     * @Author : Mr.wang
     * @param  Request  $request
     * @return JsonResponse
     */
    public function app(Request $request): JsonResponse
    {
        $validator = Validator::make($request->all(), [
            'union_id' => 'required',
            'mobileNo' => 'required|phone:CN,mobile',
            'code'     => 'required',
        ], [
            'union_id.required' => 'unionId必须填写',
            'mobileNo.required' => '手机号码必须填写',
            'mobileNo.phone'    => '手机号码格式不正确',
            'code.required'     => '验证码必须填写',
        ]);
        if ($validator->fails()) {
            return $this->failed($validator->errors()->first(), 422);
        }
        $unionId = $request->union_id;
        $wechat  = UserWechat::where('unionid', $unionId)->first();
        if (empty($wechat)) {
            $mobileNo = $request->mobileNo;
            $code     = $request->code;
            $check    = Sms::checkCode($mobileNo, $code);
            if ($check == false) {
                return $this->failed('验证码不正确', 422);
            }
            $user   = User::firstOrCreate([
                'username' => $mobileNo,
            ], [
                'password' => 111111,
            ]);
            $wechat = $user->wechat()->firstOrcreate([
                'unionid'  => $unionId,
                'nickname' => $request->nickname ?? '',
                'avatar'   => $request->avatar ?? '',
                'sex'      => $request->gender ?? 0,
                'country'  => $request->country ?? '',
                'province' => $request->province ?? '',
                'city'     => $request->city ?? '',
            ]);
            $wechat->app()->firstOrcreate([
                'openid' => $request->open_id ?? '',
            ]);
            $user->info()->update([
                'nickname' => $request->nickname ?? $user->info->nickname,
                'avatar'   => $request->avatar ?? '',
            ]);
            $token = Api::login($user);

            return $this->success([
                'token_type'   => 'Bearer',
                'access_token' => $token,
                'is_new'       => $user->wasRecentlyCreated,
            ]);
        } else {
            $token = Api::login($wechat->user);

            event(new UserLoginSuccess(Api::user(), $request, '微信授权'));

            return $this->success([
                'token_type'   => 'Bearer',
                'access_token' => $token,
                'is_new'       => false,
            ]);
        }
    }

    /**
     * Notes   : 小程序手机号登录
     *
     * @Date   : 2021/7/29 17:21
     * @Author : Mr.wang
     * @param  WechatMiniRequest  $request
     * @return JsonResponse
     * @throws InvalidConfigException
     */
    public function mini(WechatMiniRequest $request): JsonResponse
    {
        $code = $request->code;
        $this->getConfig();
        $app     = Factory::miniProgram($this->config);
        $session = $app->auth->session($code);
        if ($session->errcode) {
            return $this->failed($session->errmsg);
        }

        try {
            $decryptedData = $app->encryptor->decryptData(
                $session->session_key,
                $request->iv,
                $request->encryptedData
            );
            $mobile        = $decryptedData['purePhoneNumber'];
            $user          = User::where('username', $mobile)->first();
            if (! $user) {
                $user = User::create([
                    'username' => $mobile,
                    'password' => 111111,
                ]);
                $user->info()->create([
                    'nickname' => $request->nickname ?? '',
                    'avatar'   => $request->avatar ?? '',
                ]);
            }
            $token = Api::login($user);

            event(new UserLoginSuccess(Api::user(), $request, '微信授权'));

            return $this->success([
                'token_type'   => 'Bearer',
                'access_token' => $token,
                'is_new'       => $user->wasRecentlyCreated,
            ]);
        } catch (\Exception $exception) {
            return $this->failed($exception->getMessage());
        }
    }

    protected function getConfig()
    {
        $this->config = [
            'app_id'        => env('WECHAT_MINI_APPID'),
            'secret'        => env('WECHAT_MINI_SECRET'),
            'response_type' => 'collection',
        ];
    }

    /**
     * Notes   : 公众号登录
     *
     * @Date   : 2021/5/26 3:14 下午
     * @Author : < Jason.C >
     */
    public function official()
    {

    }

    public function query(Request $request): JsonResponse
    {
        $unionId = $request->union_id ?? '';
        if (empty($unionId)) {
            return $this->failed('', 404);
        }
        $wechat = UserWechat::where('unionid', $unionId)->first();
        if (empty($wechat)) {
            return $this->success([
                'union_id' => $unionId,
            ]);
        } else {
            $token = Api::login($wechat->user);

            event(new UserLoginSuccess(Api::user(), $request, '微信授权'));

            return $this->success([
                'token_type'   => 'Bearer',
                'access_token' => $token,
            ]);
        }
    }

    /**
     * Notes: 入库微信信息
     *
     * @Author: 玄尘
     * @Date: 2022/8/2 11:16
     */
    public function addWechatUser(): JsonResponse
    {
        try {
            $user = Api::user();
            if (! $user) {
                throw new \Exception('操作失败请登录。');
            }

            $wechatUser = $user->wechat;

            $weUser   = $this->getUserFromCode();
            $openid   = $weUser->getId();
            $baseUser = $this->getWechatUser($openid);
            $unionid  = '';
            $raw      = $weUser->getRaw();
            if (isset($raw['unionid'])) {
                $unionid = $raw['unionid'];
            }

            if (! $openid) {
                if ($raw && $raw['errmsg']) {
                    throw new \Exception($raw['errmsg']);
                }

                throw new \Exception('code解密失败');
            }

            if (! $user->info->avatar) {
                //更新头像
                $user->info->update([
                    'avatar' => $weUser->getAvatar(),
                ]);
            }


            if (! $wechatUser) {
                $wechatUser = $user->wechat()
                    ->firstOrCreate([
                        'unionid'  => $unionid,
                        'nickname' => $weUser->getNickname(),
                        'avatar'   => $weUser->getAvatar(),
                    ]);
            } elseif (empty($wechatUser['unionid']) && ! empty($unionid)) {
                $wechatUser->update([
                    'unionid' => $unionid,
                ]);
            }

            if (! $wechatUser->official) {
                $wechatUser->official()->firstOrCreate([
                    'openid'    => $weUser->getId(),
                    'subscribe' => $baseUser->subscribe
                ]);
            } else {
                $wechatUser->official()->update([
                    'subscribe' => $baseUser->subscribe
                ]);
            }

            //设置关注状态
            if ($unionid) {
                $this->setUserSubscribe($unionid, $openid, $baseUser->subscribe);
            }

            return $this->success([
                'openid'    => $openid,
                'subscribe' => $baseUser->subscribe,
            ]);
        } catch (\Exception $exception) {
            return $this->failed($exception->getMessage());
        }
    }

    /**
     * Notes: 小程序入库
     *
     * @Author: 玄尘
     * @Date: 2022/9/23 14:46
     * @param  Request  $request
     * @return JsonResponse|mixed
     */
    public function miniAddWechatUser(Request $request)
    {
        $user = Api::user();

        $validator = \Validator::make($request->all(), [
            'code'          => 'required',
            'iv'            => 'required',
            'encryptedData' => 'required',
        ], [
            'code.required'        => '缺少参数：code',
            'iv.required'          => '缺少参数：iv',
            'encryptedData.mobile' => '缺少参数：encryptedData',
        ]);

        if ($validator->fails()) {
            return $this->failed($validator->errors()->first());
        }

        try {
            $code = $request->code;

            $unionid = '';
            $weChat  = app('wechat.mini_program');
            $session = $weChat->auth->session($code);
            if (isset($session->unionid)) {
                $unionid = $session->unionid;
            }

            if (isset($session->errcode)) {
                return $this->failed($session->errmsg);
            }

            $openid     = $session->openid;
            $wechatUser = $user->wechat;

            $decryptedData = $weChat->encryptor->decryptData(
                $session->session_key,
                $request->iv,
                $request->encryptedData
            );

            if (! $wechatUser) {
                $wechatUser = $user->wechat()
                    ->firstOrCreate([
                        'unionid'  => $unionid,
                        'nickname' => $decryptedData['nickName'] ?? '',
                        'avatar'   => $decryptedData['avatarUrl'] ?? '',
                    ]);
            } elseif (empty($wechatUser['unionid']) && ! empty($unionid)) {
                $wechatUser->update([
                    'unionid' => $unionid,
                ]);
            }


            if (! $wechatUser->mini) {
                $wechatUser->mini()->firstOrCreate([
                    'openid' => $openid,
                ]);
            }

            $userSubscribe = UserSubscribe::query()
                ->where('unionid', $unionid)
                ->where('subscribe', 1)
                ->first();

            if ($userSubscribe && ! $wechatUser->official) {
                if (! $wechatUser->official) {
                    $wechatUser->official()
                        ->firstOrCreate([
                            'openid'    => $userSubscribe->openid,
                            'subscribe' => $userSubscribe->subscribe
                        ]);
                } else {
                    $wechatUser->official()->update([
                        'subscribe' => $userSubscribe->subscribe
                    ]);
                }
            }

            return $this->success([
                'openid'    => $openid,
                'subscribe' => $userSubscribe ? 1 : 0,
            ]);

        } catch (\Exception $e) {
            return $this->failed($e->getMessage());
        }
    }
}
