<?php
namespace app\controller\api;

use app\exception\RepositoryException;
use app\model\Account;
use app\repository\AccountRepository;
use app\repository\BusinessRepository;
use app\repository\CouponRepository;
use app\service\File;
use app\service\Jwt;
use app\service\Tool;
use app\service\wx\WechatApplets;
use app\validate\User as UserValidate;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use Exception;
use think\exception\ValidateException;
use think\facade\Config;
use think\response\Json;

/**
 * 用户相关
 *
 * Class User
 * @package app\controller\api
 */
class User extends Base
{
    protected $noNeedLogin = [
        'login','checkNewAccount',"decodeMobile"
    ];

    /**
     * 登录  成功返回token及用户信息
     *
     * @return Json
     * @throws InvalidConfigException
     */
    public function login(): Json
    {
        $params = [
            'code'          => $this->request->param('code', ''),
            'nick_name'     => $this->request->param('nickName', ''),
            'avatar_url'    => $this->request->param('avatarUrl', ''),
            'gender'        => $this->request->param('gender/d', 0),
            'real_name'     => $this->request->param('real_name/s', '',"trim"),
            'mobile'        => $this->request->param('mobile/s', ''),
            'lat'           => $this->request->param('lat/f', 0),
            'lng'           => $this->request->param('lng/f', 0),
        ];

        $validate = new UserValidate();
        if (!$validate->scene('wx_applets')->check($params)) {
            return $this->json(4000, $validate->getError());
        }
        $minApp = WechatApplets::getInstance();
        $jsCode = $params['code'];
        $wxUser = $minApp->auth->session($jsCode);

        if (isset($wxUser['errcode']) && $wxUser['errcode'] != 0) {
            return $this->json(4001, $wxUser['errcode'].';'.$wxUser['errmsg'] ?? '登录失败');
        }
        // $wxUser success has [session_key, openid, unionid]
        // 有效期2小时
        $wxUser['expire_time'] = time() + 7200;
        $wxUser['session_key'] = $wxUser['session_key'] ?? '';
        $openID                = $wxUser['openid'] ?? '';

        if (empty($openID)) {
            return $this->json(4002, '登录失败');
        }

        try {
            $repo       = AccountRepository::getInstance();
            $account    = $repo->findByOpenID($openID);
            $nowDate    = date('Y-m-d H:i:s');

            if (!$account) {
                if(empty($params['real_name'])){
                    return $this->json(4001, '真实姓名不能为空');
                }
                if(!is_mobile($params['mobile'])){
                    return $this->json(4001, '手机号格式错误');
                }
                // 自动注册
                $account = $repo->create([
                    'user_code'         => createUuid(), // 用户UUID
                    'open_id'           => $openID,
                    'create_time'       => $nowDate,
                    'login_time'        => $nowDate,
                    'type'              => Account::type_consumer, // 默认为普通消费者
                    'nick_name'         => $params['nick_name'] ?: generateDefaultNickName(),
                    'avatar_url'        => $params['avatar_url'] ?: Account::DEFAULT_AVATAR,
                    'gender'            => $params['gender'],
                    'real_name'         => $params['real_name'],
                    'mobile'            => $params['mobile'],
                    'lat'               => $params['lat'],
                    'lng'               => $params['lng'],
                ]);

            } else {
                $updateData     = [
                    'login_time'    => $nowDate,
                    'lat'           => empty($account->lat)?$params['lat']   :$account->lat,//如果之前的位置信息是空的
                    'lng'           => empty($account->lng)?$params['lng']   :$account->lng,//如果之前的位置信息是空的
                    'mobile'        => (!is_mobile($account->mobile))?$params['mobile']:$account->mobile,//如果之前的电话信息是空的
                    'real_name'     => empty($account->real_name)?$params['real_name']:$account->real_name,//如果之前的电话信息是空的
                ];

                // 更新资料
                $modifyStringList = ['nick_name', 'avatar_url'];
                foreach ($modifyStringList as $modifyKey) {
                    if (isset($params[$modifyKey]) && !empty($params[$modifyKey])) {
                        $updateData[$modifyKey] = $params[$modifyKey];
                    }
                }

                $repo->update($updateData, ['id' => $account['id']]);
                $account = $repo->findById($account['id']);
            }

        } catch (RepositoryException | Exception $e) {
            return $this->json(4003, '登录失败!'.$e->getMessage());
        }

        $account = $account->toArray();
        $account['avatar_url'] = File::convertCompleteFileUrl($account['avatar_url']);
        $jwtData = [
            'user_id'       => $account['id'],
            'user_code'     => $account['user_code'],
            'open_id'       => $openID,
            'session_key'   => $wxUser['session_key'],
            'expire_time'   => $wxUser['expire_time'],
        ];


        $data   = [
            'avatar'        => File::convertCompleteFileUrl($account['avatar_url']),
            'nickName'      => $account['nick_name'],
            'token'         => Jwt::generate($jwtData),
            'userType'      => $account['type'],
            'userTypeDes'   => Account::accountTypeDescList()[$account['type']] ?? '游客',
        ];
        return $this->json(0, 'success', $data);
    }

    /*
     * 获取个人中心资料
     */
    public function getUserCenterInfo()
    {
        $accountId = $this->request->user['user_id'] ?? 0;

        try {
            $accountRepo    = AccountRepository::getInstance();
            $couponRepo     = CouponRepository::getInstance();
            $busRepo        = BusinessRepository::getInstance();

            $account        = $accountRepo->findById($accountId, [], function ($q) {
                return $q->with(['business', 'parent']);
            });
            if (empty($account)) {
                throw new ValidateException('用户无效！');
            }

            if ($account['type'] == Account::type_business) {
                // 商家用户
                if (empty($account['business'])) {
                    throw new ValidateException('用户无效！没有相关的商户信息记录');
                }

                $businessRes    = [
                    'avatar'    => File::convertCompleteFileUrl($account['avatar_url']),
                    'nickName'  => $account['nick_name'],
                    'userType'  => $account['type'],
                    'userTypeDes'   => Account::accountTypeDescList()[$account['type']] ?? '游客',
                    'couponCount'   => 0,
                    'business'      => [
                        'code'          => $account['business']['code'],
                        'businessName'  => $account['business']['business_name'],
                        'state'         => $account['business']['state'],
                        'reason'        => $account['business']['reason'],
                        'balance'       => $account['business']['balance'],
                        'enable'        => $account['business']['enable'],
                    ],
                    "alertMoney"=>config("wechat.balance"),
                    "redPrice"=>CouponRepository::getInstance()->getUserRedPrice( $account['user_code']),
                ];

                return $this->json(0, 'success', $businessRes);
            } else {
                // 用户领取的优惠卷总数量
                $couponCount    = $couponRepo->getModel()::getCountByWhere(['consumer_code' => $account['user_code']]);
                $personalRes    = [
                    'avatar'    => File::convertCompleteFileUrl($account['avatar_url']),
                    'nickName'  => $account['nick_name'],
                    'userType'  => $account['type'],
                    'userTypeDes'   => Account::accountTypeDescList()[$account['type']] ?? '游客',
                    'couponCount'   => $couponCount,
                    "alertMoney"=>config("wechat.balance"),
                    "redPrice"=>CouponRepository::getInstance()->getUserRedPrice( $account['user_code']),

                ];


                if ($account['type'] == Account::type_staff) {
                    // 员工
                    $businessCode = $account['parent']['business_code'] ?? '';
                    if (!empty($businessCode)) {
                        $business = $busRepo->findOneByWhere(['code' => $businessCode]);
                        if ($business) {
                            $personalRes['business'] = [
                                'code'          => $business['code'],
                                'businessName'  => $business['business_name'],
                                'state'         => $business['state'],
                                'reason'        => $business['reason'],
                                'balance'       => $business['balance'],
                                'enable'        => $business['enable'],
                            ];
                        }
                    }

                    $personalRes['parent'] = [];
                    if (!empty($account['parent'])) {
                        $personalRes['parent'] = [
                            'avatar'    => File::convertCompleteFileUrl($account['parent']['avatar_url']),
                            'nickName'  => $account['parent']['nick_name'],
                            'userType'  => $account['parent']['type'],
                            'userTypeDes'   => Account::accountTypeDescList()[$account['parent']['type']] ?? '',
                            'couponCount'   => 0,
                            'businessCode'  => $account['parent']['business_code'],
                        ];
                    }

                } elseif(!empty($account['business'])) {
                    // 商户认证记录
                    $personalRes['business'] = [
                        'state'     => $account['business']['state'],
                        'reason'    => $account['business']['reason'],
                    ];
                }

                return $this->json(0, 'success', $personalRes);
            }

        } catch (ValidateException $e) {
            return $this->json(4001, $e->getError());
        } catch (Exception $e) {
            return $this->json(5001, '服务器繁忙！获取用户个人信息失败');
        }
    }

    //检查是新用户还是老用户
    public function checkNewAccount()
    {
        Config::load('extra/wechat', 'wechat');
        $config = config('wechat');
        $code = $this->request->param('code/s');
        $appId = $config["applets_appId"]??'';//appid
        $appSecret = $config["applets_appSecret"]??'';//appsecret
        $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='
            . $appId
            . '&secret='
            . $appSecret
            . '&js_code='
            . $code
            . '&grant_type=authorization_code';
        $data = json_decode(Tool::httpRequest($url, "get"), true);

        //返回状态
        if (isset($data["openid"])) {
            $account = AccountRepository::getInstance()->findByOpenID($data["openid"]);
            if(empty($account)){
                return $this->json(0, "success",[
                    "showMobile"=>true,
                    "showRealName"=>true,
                    "session_key"=>$data["session_key"]]);
            }
            return $this->json(0, "success",[
                "showMobile"=>is_mobile($account->mobile)?false:true,
                "showRealName"=>(!empty($account->real_name))?false:true,
                "session_key"=>$data["session_key"]
            ]);
        }
        return $this->json(5001, "获取登录状态失败", ["showMobile"=>true,
                "showRealName"=>true,
                "session_key"=>'']);
    }

    /**
     * 解密手机号
     * */
    public function decodeMobile()
    {
        $params    = input('post.');
        $rules = [
            'encryptedData|加密数据'        => 'require',
            'iv|IV'                         => 'require',
            'session_key|会话标识'          => 'require',
        ];

        $validate = $this->validateByApi($params, $rules);

        if ($validate !== true) {
            return $validate;
        }

        // 解密手机相关数据
        $minApp      = WechatApplets::getInstance();
        $sessionKey  = $params['session_key'] ?? '';
        $decryptData = $minApp->encryptor->decryptData($sessionKey, $params['iv'], $params['encryptedData']);
        $phone       = $decryptData['phoneNumber'] ?? ''; // 通过iv和加密数据 解密出手机号

        if ($phone) {
         return $this->json(0,"success",["mobile"=>$phone]);
        }
        return $this->json(5001,"获取手机号失败");
    }

}