<?php

namespace addons\fastim\controller\api;

use app\lib\model\FamilyModel;
use app\lib\model\FamilyTreeMateModel;
use app\lib\model\FamilyTreeModel;
use app\lib\service\FamilyTreeService;
use think\Db;
use fast\Random;
use think\Config;
use think\Exception;
use think\Validate;
use app\common\library\Sms;
use addons\fastim\library\Common;
use addons\fastim\library\Captcha;

/**
 * im会员登录
 */
class User extends Base
{
    protected $noNeedLogin = ['login', 'register', 'captcha', 'captchaPre','createfamily','forgetpassword'];

    protected $userInfo = false;

    public function _initialize()
    {
        parent::_initialize();
    }

    /**
     * 支持账户和手机号登录
     */
    public function login()
    {
        $tab       = $this->request->post('tab');
        $code      = $this->request->post('code');
        $account   = $this->request->post('account');
        $password  = $this->request->post('password');
        $captcha   = $this->request->post('captcha');
        $captchaId = $this->request->post('captcha_id');

        if ($tab == 1) {
            if (!$account || !Validate::regex($account, "^1\d{10}$")) {
                $this->error(__('Please enter the correct mobile phone number'));
            }

            // 手机验证码检查
            $codeResult = Sms::check($account, $code, 'login');
            if (!$codeResult) {
                $this->error(__('Captcha is incorrect'));
            }

            $user = \app\common\model\User::get(['mobile' => $account]);
            if ($user) {
                if ($user->status != 'normal') {
                    $this->error(__('Abnormal account status'));
                }
                $this->userInfo = $this->directLogin($user);
                Sms::flush($account, 'login');
            } else {
                // 注册
                $userInfo = $this->createUser('', '', '', $account, []);
                Sms::flush($account, 'login');
                $this->success(__('Sign up successful'), [
                    'userinfo' => $userInfo
                ]);
            }
        } else {
            $rule = [
                'account'    => 'require|length:3,30',
                'password'   => 'require|length:6,30',
                'captcha'    => 'require|length:4,6',
                'captcha_id' => 'require'
            ];
            $msg  = [
                'captcha.require'    => 'Please enter the verification code',
                'captcha.length'     => 'Please enter the correct verification code',
                'captcha_id.require' => 'Invalid parameter',
                'account.require'    => 'Username can not be empty',
                'account.length'     => 'Username must be 3 to 30 characters',
                'password.require'   => 'Password can not be empty',
                'password.length'    => 'Password must be 6 to 30 characters'
            ];
            $data = [
                'account'    => $account,
                'password'   => $password,
                'captcha'    => $captcha,
                'captcha_id' => $captchaId
            ];

            $validate = new Validate($rule, $msg);
            $result   = $validate->check($data);
            if (!$result) {
                $this->error(__($validate->getError()));
            }

            $captchaObj = new Captcha();
            if (!$captchaObj->check($captcha, $captchaId)) {
                $this->error(__('Please enter the correct verification code'));
            }

            // 检查是否为会员
            $this->userInfo = $this->checkUserByPassword($account, $password);
            if (!$this->userInfo) {
                // 检查是否为管理员
                $this->userInfo = $this->checkAdminByPassword($account, $password);
            }
            if (!$this->userInfo) {
                $this->error(__('Username or password is incorrect'));
            }
        }

        // 用户和管理员以及游客token都可通过此处转换为IMuser
        $imUser = Common::checkIMUser(false, $this->userInfo);
        if (!$imUser) {
            // 建立
            $imUser = Common::createIMUser($this->request->get('referrer') ?? '', $this->request->ip());
            if ($imUser) {
                $userInfoToken = $imUser['cache_token'];
            }
        } else {
            $keeptime      = 864000;// token 10天后过期
            $expiretime    = time() + $keeptime;
            $token         = Db::name('fastim_user')->where('id', $imUser['id'])->value('token');
            $key           = md5(md5($imUser['id']) . md5($keeptime) . md5($expiretime) . $token);
            $userInfoToken = [$imUser['id'], $keeptime, $expiretime, $key];
            $userInfoToken = implode('|', $userInfoToken);
        }

        // 绑定
        $this->userInfo = Common::bindFaUserToIMUser($imUser, $this->userInfo);
        if (!$this->userInfo) {
            $this->error(__('Unrecognized user'), [], 401);
        }

        $this->userInfo['token']      = $userInfoToken;
        $this->userInfo['auth_token'] = Common::createAuthToken($imUser['id']);
        $this->userInfo['user_token'] = $this->getRefreshtoken($imUser['user_id']);
        $this->success('ok', [
            'userinfo' => $this->userInfo
        ]);
    }

    public function captchaPre()
    {
        $captchaId = md5(Random::uuid());
        $this->success('', [
            'captcha_id' => $captchaId
        ]);
    }

    public function captcha()
    {
        $captchaId = $this->request->request('captcha_id');
        $config    = array(
            'codeSet'  => '123456789',            // 验证码字符集合
            'fontSize' => 22,                     // 验证码字体大小(px)
            'useCurve' => false,                  // 是否画混淆曲线
            'useNoise' => true,                   // 是否添加杂点
            'length'   => 4,                      // 验证码位数
            'bg'       => array(255, 255, 255),   // 背景颜色
        );

        $captcha = new Captcha($config);
        return $captcha->entry($captchaId);
    }

    public function register()
    {
        $mobile   = $this->request->post('mobile');
        $username = $this->request->post('username');
        $password = $this->request->post('password');
        $captcha  = $this->request->post('captcha');
        $realname = $this->request->post('realname');
        $surname_id=$this->request->param("surname_id");//姓氏
        $sex=$this->request->param("sex");//姓氏


        $rule = [
            'mobile'   => 'regex:/^1\d{10}$/',
            'username' => 'require|length:3,30',
            'realname' => 'require|length:1,30',
            'surname_id' => 'require|length:1,3',
            'password' => 'require|length:6,30'
        ];
        $msg  = [
            'mobile'           => 'Mobile is incorrect',
            'username.require' => 'Username can not be empty',
            'username.length'  => 'Username must be 3 to 30 characters',
            'password.require' => 'Password can not be empty',
            'password.length'  => 'Password must be 6 to 30 characters',
            'realname.require' => 'Realname can not be empty',
            'surname_id.require' => 'Surname_id can not be empty',
        ];
        $data = [
            'mobile'   => $mobile,
            'username' => $username,
            'password' => $password,
            'captcha'  => $captcha,
            'realname'  => $realname,
            'surname_id'  => $surname_id,
        ];

        $captchaResult = Sms::check($mobile, $captcha, 'register');
        if (!$captchaResult) {
            $this->error(__('Captcha is incorrect'));
        }

        $validate = new Validate($rule, $msg);
        $result   = $validate->check($data);
        if (!$result) {
            $this->error(__($validate->getError()));
        }

        $userInfo = $this->createUser($username, $password, '', $mobile, ['surname_id'=>$surname_id,'realname'=>$realname]);
        $userInfo['user_token'] = $this->getRefreshtoken($userInfo['user_id']);
        $this->createFamily($surname_id,$realname,$userInfo['user_id'],$userInfo['id'],$sex);
        Sms::flush($mobile, 'register');
        $this->success(__('Sign up successful'), [
            'userinfo' => $userInfo
        ]);
    }

    /**
     *生成样谱
     */
    public function createFamily($surname_id=0,$realname='',$user_id=0,$imuser_id=0,$sex = 0)
    {
//        $surname_id   = $this->request->post('surname_id');
//        $realname   = $this->request->post('realname');
//        $user_id   = $this->request->post('user_id');
//        $imuser_id   = $this->request->post('imuser_id');
//        $sex   = $this->request->post('sex');
        $params['surname_id']=$surname_id;
        $params['realname']=$realname;
        $params['family_name']=Db::name("surname")->where(['ID'=>$surname_id])->value("Surname");
//        $params['province_id']=$this->request->param("province_id");
//        $params['city_id']=$this->request->param("city_id");
//        $params['area_id']=$this->request->param("area_id");
//        $params['town_id']=$this->request->param("town_id");
//        $params['village_id']=$this->request->param("village_id");
//        $params['address']=$this->request->param("address");
        $params['create_user_id']=$user_id;
        $params['rw_user_id']=$user_id;
        $params['fastim_id']=$imuser_id;
        $params['status']=0;
        $res=FamilyModel::dataAdd($params);
//        unset($params['surname_id'],$params['realname'],$params['family_name']);
        //添加初始成员
        $one_ret = $this->createTree($params,$res->id,$user_id,1);//上两代
        if($one_ret['code']<1){
            $this->error('失败',$one_ret);
        }
        $two_ret = $this->createTree($params,$res->id,$user_id,2,$one_ret['data']['parent_id'],$sex);//上一代
        $three_ret = $this->createTree($params,$res->id,$user_id,3,$two_ret['data']['parent_id'],$sex);//本人
        $four_ret = $this->createTree($params,$res->id,$user_id,4,$three_ret['data']['parent_id'],$sex);//下一代
//        $this->success('successful');
        return ['code' =>1,'msg'=>'生成样谱成功'];
    }

    /**
     * @param $params
     * @param $family_id
     * @param $create_user_id
     * @param int $level
     * @return array
     * 批量生成谱树
     */
    protected function createTree($params,$family_id,$create_user_id,$level=3,$parent_id=0,$sex=0){
        Db::startTrans();
        try{
            switch ($level){
                case 1:
                    $first['name'] = $params['realname'].'爷爷';
                    $first['ext5'] = '白';
                    $first['sex'] = 1;
                    $first['type'] = '爷爷';
                    $first_mate['sex'] = 2;
                    $first_mate['name']=$params['realname'].'奶奶';
                    break;
                case 2:
                    $first['name'] = $params['realname'].'之父';
                    $first['ext5'] = '日';
                    $first['sex'] = 1;
                    $first['type'] = '父亲';
                    $first_mate['sex'] = 2;
                    $first_mate['name']=$params['realname'].'妈妈';
                    break;
                case 3:
                    $first['name'] = $params['realname'];
                    $first['ext5'] = '依';
                    $first['type'] = '本人';
                    $first['sex'] = $sex;
                    $first_mate['sex'] = $sex == 1 ? 2 : 1;
                    $first_mate['name']=$params['realname'].'配偶';
                    break;
                case 4:
                    $first['name'] = $params['realname'].'之子';
                    $first['ext5'] = '山';
                    $first['type'] = '儿子';
                    $first['sex'] = 1;
                    $first_mate['sex'] = 2;
                    $first_mate['name']=$first['name'].'媳妇';
                    break;
            }
            //添加初始成员
            $first['is_pay'] = 1;
            $first['surname'] = $params['family_name'];
            $first['firstname'] = $first['name'];
            $people=FamilyTreeService::addFamilyPeople($first,$family_id);
            $first['family_id'] = $family_id;
            $first['level'] = $level;//处于第三代
            $first['people_id']=$people['id'];
            $first['parent_id'] = $parent_id;
            $first['create_user_id'] = $create_user_id;
            $first['name'] = $params['family_name'].$first['name'];
            unset($first['ext5']);
            unset($first['is_pay']);
            unset($first['surname']);
            unset($first['firstname']);
            $tree=FamilyTreeModel::dataAdd($first);
            //添加配偶
            $first_mate['is_pay'] = 1;
            $first_mate['surname'] = $params['family_name'];
            $first_mate['firstname'] = $first_mate['name'];
            $mate_people=FamilyTreeService::addFamilyPeople($first_mate,$family_id);
            $first_mate['family_tree_id']=$tree->id;
            $first_mate['create_user_id']=$create_user_id;
            $first_mate['people_id']=$mate_people['id'];
            $first_mate['name'] = $params['family_name'].$first_mate['name'];
            unset($first_mate['is_pay']);
            unset($first_mate['surname']);
            unset($first_mate['firstname']);
            $mate_tree=FamilyTreeMateModel::dataAdd($first_mate);
            Db::commit();
        }catch (Exception $e){
            Db::rollback();
            return['code' =>0,'msg' =>$e->getMessage()];
        }
        return['code' =>1,'msg' =>'生成样谱成功','data' =>['parent_id' =>$tree->id]];
    }

    private function createUser($username, $password, $email = '', $mobile = '', $extend = [])
    {
        $auth = \app\common\library\Auth::instance();
        if ($username) {
            $ret = $auth->register($username, $password, '', $mobile, $extend);
        } else {
            $ret = $auth->register($mobile, \fast\Random::alnum(), '', $mobile, $extend);
        }
        if ($ret) {
            $userInfo             = $auth->getUserinfo();
            $userInfo['identity'] = 'fauser';

            // 建立imUser
            $imUser = Common::createIMUser('uni-app', $this->request->ip());
            // 绑定
            $userInfo = Common::bindFaUserToIMUser($imUser, $userInfo);
            if (!$userInfo) {
                $this->error(__('Failed to bind new user, please try again'), [], 401);
            }

            $userInfo['token']      = $imUser['cache_token'];
            $userInfo['auth_token'] = Common::createAuthToken($imUser['id']);
            unset($userInfo['cache_token']);
//            $userInfo['imuser_id'] =$imUser['id'];
            return $userInfo;
        } else {
            $this->error($this->auth->getError());
        }
    }

    /**
     * 直接登录
     */
    private function directLogin($user)
    {
        Db::startTrans();
        try {
            //判断连续登录和最大连续登录
            if ($user->logintime < \fast\Date::unixtime('day')) {
                $user->successions    = $user->logintime < \fast\Date::unixtime('day', -1) ? 1 : $user->successions + 1;
                $user->maxsuccessions = max($user->successions, $user->maxsuccessions);
            }

            $user->prevtime = $user->logintime;
            //记录本次登录的IP和时间
            $user->loginip   = request()->ip();
            $user->logintime = time();
            //重置登录失败次数
            $user->loginfailure = 0;

            $user->save();
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            return false;
        }

        $user->identity = 'fauser';
        return $user->toArray();
    }

    private function checkUserByPassword($account, $password)
    {
        $field = Validate::is($account, 'email') ? 'email' : (Validate::regex($account, '/^1\d{10}$/') ? 'mobile' : 'username');
        $user  = \app\common\model\User::get([$field => $account]);
        if (!$user) {
            return false;
        }
        if ($user->status != 'normal') {
            return false;
        }
        $auth = \app\common\library\Auth::instance();
        if ($user->password != $auth->getEncryptPassword($password, $user->salt)) {
            return false;
        }
        return $this->directLogin($user);
    }

    private function checkAdminByPassword($username, $password)
    {
        $admin = \app\admin\model\Admin::get(['username' => $username]);
        if (!$admin) {
            return false;
        }
        if ($admin['status'] == 'hidden') {
            return false;
        }
        if (Config::get('fastadmin.login_failure_retry') && $admin->loginfailure >= 10 && time() - $admin->updatetime < 86400) {
            return false;
        }
        if ($admin->password != md5(md5($password) . $admin->salt)) {
            $admin->loginfailure++;
            $admin->save();
            return false;
        }

        // 不重置管理员token
        $admin->loginfailure = 0;
        $admin->logintime    = time();
        $admin->loginip      = request()->ip();
        $admin->save();
        $admin->identity = 'admin';
        return $admin->toArray();
    }

    /**
     * 忘记登录密码
     */
    public function forgetPassword(){
        $account   = $this->request->post('account');
        $first_password = $this->request->post('first_password', 0);
        $second_password = $this->request->post('second_password', 0);
        $code = $this->request->post('code');//验证码
        if (!$account || !Validate::regex($account, "^1\d{10}$")) {
            $this->error(__('Please enter the correct mobile phone number'));
        }
        $user = \app\common\model\User::get(['mobile' => $account]);
        if(!$user){
            $this->error(__('Abnormal account status'));
        }
        if ($user->status != 'normal') {
            $this->error(__('Abnormal account status'));
        }
        if (!$first_password) {
            $this->error('请输入第一次密码');
        }
        if (!$second_password) {
            $this->error('请输入第二次密码');
        }
        if ($first_password != $second_password) {
            $this->error('两次密码不一致');
        }
        // 手机验证码检查
        $codeResult = Sms::check($account, $code, 'forget_password');
        if (!$codeResult) {
            $this->error(__('Captcha is incorrect'));
        }
        $auth = \app\common\library\Auth::instance();
        $password = $auth->getEncryptPassword($second_password, $user->salt);
        $res = \app\common\model\User::update(['password' => $password],['mobile' => $account]);
        $this->success('设置成功');

    }
}