<?php

namespace App\Http\Controllers\App;

use App\Facades\AliyunService;
use App\Facades\ChatService;
use App\Facades\CommonService;
use App\Facades\UploadService;
use App\Facades\UserService;
use App\Http\Controllers\Controller;
use App\Http\Response\ResponseJson;
use App\Jobs\SendEasySms;
use App\Jobs\SendMail;
use App\Jobs\SyncSaasUser;
use App\Mail\SendEmailCode;
use App\Models\Collaborator;
use App\Models\DmaServiceUserRole;
use App\Models\Message;
use App\Models\User;
use App\Models\WangYiYun;
use App\Services\ImService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use Closure;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use cccdl\yunxin_sdk\Im\User as ImUser;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

class LoginController extends Controller
{
    use ResponseJson;

    /**
     * 密码登录
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
     */
    public function pwdLogin(Request $request)
    {
        //检测输入
        list($user, $message) = $this->checkPwdLogin($request);
        if ($message) return $this->failure($message);
        if ($user->isBan()) return $this->banFail("账号已被封，请联系客服");
        $user = $this->loginInfo($user);
        return $this->success('ok', $user);
    }

    /**
     * 验证码登录
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
     */
    public function codeLogin(Request $request)
    {
        //检测输入
        list($user, $message) = $this->checkCodeLogin($request);
        if ($message) return $this->failure($message);
        if ($user->isBan()) return $this->banFail("账号已被封，请联系客服");
        $user = $this->loginInfo($user);
        return $this->success('ok', $user);
    }

    /**
     * 注册登录一起(只有手机号登录)
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
     */
    public function mobileRegisterLogin(Request $request){
        $mobile = $request->input('mobile');
        $is_server = $request->input('is_server');
        $source = User::APP_USER_SOURCE;
        if($is_server){
            $source = User::SERVER_USER_SOURCE;
        }
        $en_mobile = aesEncryptCBC($mobile);
        Log::Info($mobile);
        Log::Info($en_mobile);

        $exists = User::whereIn('mobile',[$en_mobile,$mobile])->whereIn('source',$source)->exists();
        if(!$exists){
            $message = $this->checkRegister($request,true);
            if ($message) return $this->failure($message);
            $data = $request->all();
            $data['mobile'] = $en_mobile;
            $user = $this->registerUser($data);
        }else{
            //检测输入
            list($user, $message) = $this->checkCodeLogin($request);
            if ($message) return $this->failure($message);
            if ($user->isBan()) return $this->banFail("账号已被封，请联系客服");
        }
        $this->updateLoginInfo($request,$user->id);
        $user = $this->loginInfo($user);
        return $this->success('ok', $user);
    }

    public function localRegisterLogin(Request $request){
        // $mobile = $request->input('mobile');
        // $is_server = $request->input('is_server');
        // $source = User::APP_USER_SOURCE;
        // if($is_server){
        //     $source = User::SERVER_USER_SOURCE;
        // }
        // $en_mobile = aesEncryptCBC($mobile);
        // $exists = User::whereIn('mobile',[$en_mobile,$mobile])->whereIn('source',$source)->exists();
        // if(!$exists){
        //     $message = $this->checkRegister($request,true);
        //     if ($message) return $this->failure($message);
        //     $data = $request->all();
        //     $data["mobile"] = $en_mobile;
        //     $user = $this->registerUser($data);
        // }else{
            //检查阿里云token
            list($user, $message) = $this->checkLocalLogin($request);
            if ($message) return $this->failure($message);
            if ($user->isBan()) return $this->banFail("账号已被封，请联系客服");
        // }
        $this->updateLoginInfo($request,$user->id);
        $user = $this->loginInfo($user);
        return $this->success('ok', $user);
    }

    public function updateLoginInfo($request,$user_id){
        $phone_model = $request->input('phone_model');
        $system_version = $request->input('system_version');
        $platform = $request->header("source");
        $version = $request->header("version");
        $ip = get_real_ip();
        $open_id = $request->input('open_id');
        User::where('id',$user_id)->update(['phone_model'=>$phone_model,'system_version'=>$system_version,'platform'=>$platform,'version'=>$version,'ip'=>$ip,'open_id'=>$open_id]);
    }
    public function localLogin(Request $request)
    {
        //检查阿里云token
        list($user, $message) = $this->checkLocalLogin($request);
        if ($message) return $this->failure($message);
        if ($user->isBan()) return $this->banFail("账号已被封，请联系客服");
        $user = $this->loginInfo($user);
        return $this->success('ok', $user);
    }

    /**
     * 注册
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
     */
    public function register(Request $request)
    {
        $message = $this->checkRegister($request);
        if ($message) return $this->failure($message);
        $data = $request->all();
        if ($request->mobile) {
            $data["mobile"] = aesEncryptCBC($request->mobile);
        }
        $data['password'] = Hash::make($data['passwd']);
        $user = $this->registerUser($data);
        $user = $this->loginInfo($user);
        return $this->success('ok', $user);
    }

    public function registerUser($data)
    {
        //云康宝体脂秤;
        $data['fat_device'] = User::FAT_DEVICE_YUNKANGBAO;
        $data['source'] = User::SOURCE_APP;
        if(isset($data['is_server']) && $data['is_server'] == User::IS_SERVER){
            $data['source'] = User::SOURCE_APP_SERVER;
        }
        DB::beginTransaction();
        $user = User::create($data);
        $user->userInfo()->create();
        //记录分享人
        if (request()->from_user_id){
            $user->shareUserLog()->create(['share_user_id'=>request()->from_user_id, 'channel'=>'APP']);
        }
        DB::commit();
        return $user;
    }

    /**
     * 登录信息
     * @param $user
     * @return mixed
     */
    public function loginInfo($user)
    {
        //获取登录信息
//        $user = $this->userToken($user);
        //jwt token
        $user->token = UserService::apiJwtToken($user);
        $user->makeVisible('api_token');
        $user->makeVisible('mobile');
        //同步saas用户
//        SyncSaasUser::dispatch($user)->onQueue('health');
        //是否完善基本资料
        $user->is_complete_profile = $user->baseUserInfo();

        $status = "NOORDER";
        $order = $user->payOrders()->whereIn('status', ['NOTSTART', 'STARTING','FINISHED'])->first();
        if ($order) $status = $order->status;
        $user->order_status = $status;
        $user->service_status = $order->service_status??"NOINFO";
        //测试
        if($user->id == 336){
            $user->is_servicer = 1;
        }
        //判断用户信息
        $user->unit = get_user_unit($user->language,$user->unit);

        //查看手机号是否存在服务人员信息
//        $collaborator = User::getOfficialUser($user->mobile);
//        if($collaborator && $collaborator->user_id != $user->id){
//            User::sameDataToUser($collaborator->user_id,$user->id);
//        }
        //创建网易云信账号
        $imService = new ImService();
        $imService->updateImUser($user->id,$user);

        $imUser = $user->imUser;
        $user->im_token = $imUser->token;
        $user->ac_cid = $imUser->accid;
        $user->is_servicer = $user->serviceUser?1:0;
        $user->user_id = $user->id;
        $user->id = make_user_id($user->id);
        //是否有服务角色
        $dmaRole = DmaServiceUserRole::where("user_id", $user->user_id)->where("status",1)->first();
        $user->dma_servicer = $dmaRole?1:0;
        return $user;
    }
    /**
     * 登录token
     * @param $user
     * @return mixed
     */
//    public function userToken($user)
//    {
//        if (!$user->expire_at || $user->expire_at < date('Y-m-d H:i:s')){
//            $carbon_expire_at = Carbon::now()->addDays(30);
//            $expire_at = $carbon_expire_at->toDateTimeString();
//            $api_token = $user->createToken($user->id, ['*'], $carbon_expire_at)->plainTextToken;
//            User::where('id',$user->id)->update(['api_token'=>$api_token, 'expire_at'=>$expire_at]);
//            $user->api_token = $api_token;
//        }
//        $user->makeVisible('api_token');
//        $user->makeVisible('mobile');
//
//        return $user;
//    }

    public function checkLocalLogin($request)
    {
        $data = [
            'access_token'=>['required'],
        ];
        //验证输入
        $validated = Validator::make($request->all(), $data, [
            'access_token.required'=>'缺少阿里云token',
        ]);
        $errors = $validated->errors()->all();
        $error = count($errors)?$errors[0]:null;
        $user = null;
        if (empty($error)) {
            //todo 检查阿里云token和手机号是否匹配
            $mobile = AliyunService::getLocalMobile();
            if (empty($mobile)) throw new \Exception("获取本机号码失败");
            //用户信息
            $is_server = $request->input('is_server');
            $source = User::APP_USER_SOURCE;
            if($is_server){
                $source = User::SERVER_USER_SOURCE;
            }
            $en_mobile = aesEncryptCBC($mobile);
            $user = User::whereIn("mobile", [$en_mobile, $mobile])->whereIn('source',$source)->first();
            if (empty($user)) {
                $arr = ['mobile'=>$en_mobile, 'password'=>null,'area_code'=>86];
                $user = $this->registerUser($arr);
            }
        }
        return [$user, $error];
    }

    /**
     * 验证账号密码
     * @param $request
     * @return array
     */
    public function checkPwdLogin($request)
    {
        $is_server = $request->input('is_server');
        $source = User::APP_USER_SOURCE;
        if($is_server){
            $source = User::SERVER_USER_SOURCE;
        }
        $data = [
            'password'=>['required'],
        ];
        $data['mobile'] = [ 'required',
            function (string $attribute, mixed $value, Closure $fail) use($source){
                $en_value = aesEncryptCBC($value);
                $type = filter_var($value, FILTER_VALIDATE_EMAIL)?'email':'mobile';
                $exists = User::whereIn($type, [$en_value, $value])->whereIn("source", $source)->exists();
                if ($type == 'mobile') {
                    if (empty($exists)) $fail("手机号未注册");
                }else {
                    if (empty($exists)) $fail("邮箱未注册");
                }
            },
        ];
        //验证输入
        $validated = Validator::make($request->all(), $data, [
            'mobile.required'=>'请输入账号',
            'password.required'=>'请输入密码',
        ]);
        $errors = $validated->errors()->all();
        $error = count($errors)?$errors[0]:null;
        $user = null;
        if (empty($error)) {
            //密码是否正确
            $type = filter_var($request->mobile, FILTER_VALIDATE_EMAIL)?'email':'mobile';
            if ($type == "mobile") {
                $en_mobile = aesEncryptCBC($request->mobile);
                $user = User::whereIn("mobile", [$en_mobile, $request->mobile])->whereIn("source", $source)->first();
            }else {
                $user = User::where("email", $request->mobile)->whereIn("source", $source)->first();

            }
            $res = Hash::check($request->password, $user->password);
            if (empty($res)) $error = "账号密码不匹配";

        }
        return [$user, $error];
    }

    /**
     * 验证账号验证码
     * @param $request
     * @return array
     */
    public function checkCodeLogin($request)
    {
        //验证输入
        $data = [
            'code'=>['required'],
        ];
        $data['mobile'] = [ 'required',
            function (string $attribute, mixed $value, Closure $fail) {
                $en_value = aesEncryptCBC($value);
                $type = filter_var($value, FILTER_VALIDATE_EMAIL)?'email':'mobile';
                if ($type == "mobile") {
                    $exists = User::whereIn($type, [$value, $en_value])->exists();
                }else {
                    $exists = User::where($type, $value)->exists();
                }
                if ($type == 'mobile') {
                    if (empty($exists)) $fail("手机号未注册");
                }else {
                    if (empty($exists)) $fail("邮箱未注册");
                }
            },
        ];
        $validated = Validator::make($request->all(), $data, [
            'mobile.required'=>'请输入账号',
            'code.required'=>'请输入验证码',
        ]);
        $errors = $validated->errors()->all();
        $error = count($errors)?$errors[0]:null;
        $user = null;
        $is_server = $request->input('is_server');
        $source = User::APP_USER_SOURCE;
        if($is_server){
            $source = User::SERVER_USER_SOURCE;
        }
        if (empty($error)) {
            //验证码是否正确
            $mobile = $request->mobile; 
            $en_mobile = aesEncryptCBC($mobile);
            $type = filter_var($request->mobile, FILTER_VALIDATE_EMAIL)?'email':'mobile';
            if ($type == 'mobile') {
                $user = User::whereIn($type, [$en_mobile, $mobile])->whereIn('source',$source)->first();
                $res = Message::checkCode($request->mobile, $request->code);
            }else {
                $user = User::where($type, $mobile)->whereIn('source',$source)->first();
                $res = Message::checkEmailCode($request->mobile, $request->code);
            }
            if (empty($res)) $error = "账号验证码不匹配";
        }
        return [$user, $error];
    }

    public function checkRegister($request,$is_mobile_register=false)
    {
        //用户信息
        $is_server = $request->input('is_server');
        $source = User::APP_USER_SOURCE;
        if($is_server){
            $source = User::SERVER_USER_SOURCE;
        }
        $route = $request->route()->action['as'];
        $data = [
            'code'=>['required'],
            'passwd'=>['required'],
            'confirm_passwd'=>['required',
                function (string $attribute, mixed $value, Closure $fail) use($request) {
                    if ($value != $request->passwd) $fail('密码不一致');
                },
            ],
        ];

        if($is_mobile_register){
            $data = [
                'code'=>['required'],
            ];
        }
        if ($route == 'app.mobile.register' || $route == 'app.mobile.register.login') {
            $data['mobile'] = [ 'required',
                function (string $attribute, mixed $value, Closure $fail) use($source) {
                    $exists = User::where($attribute, $value)->whereIn('source',$source)->exists();
                    if ($exists) $fail("手机号已注册");
                },
            ];
        }else {
            $data['email'] = [ 'required',
                function (string $attribute, mixed $value, Closure $fail) use($source) {
                    $exists = User::where($attribute, $value)->whereIn('source',$source)->exists();
                    if ($exists) $fail("邮箱已注册");
                },
            ];
        }
        $validated = Validator::make($request->all(), $data, [
            'mobile.required'=>'请输入手机号',
            'code.required'=>'请输入验证码',
            'email.required'=>"请输入邮箱",
            'passwd.required'=>'请输入密码',
            'confirm_passwd.required'=>'请输入确认密码'
        ]);
        $errors = $validated->errors()->all();
        $error = count($errors)?$errors[0]:null;
        if (empty($error)) {
//            if(config('app.env') == 'production'){
                //验证码是否正确
                if ($route == 'app.mobile.register' || $route == 'app.mobile.register.login') {
                    $res = Message::checkCode($request->mobile, $request->code);
                    if (empty($res)) $error = "手机号验证码不匹配";
                }else {
                    $res = Message::checkEmailCode($request->email, $request->code);
                    if (empty($res)) $error = "邮箱验证码不匹配";
                }
//            }
        }
        return $error;
    }

    public function sendEmailCode(Request $request)
    {
        //验证输入
        $message = $this->checkSendEmailCode($request);
        if ($message) return $this->failure($message);
        //发送邮箱
        SendMail::dispatch('code', ['email'=>$request->email])->onQueue('health');
        return $this->success('ok');
    }

    public function checkSendEmailCode($request)
    {
        $validated = Validator::make($request->all(),[
            'email'=> [
                'required', function(string $attribute, mixed $value, Closure $fail){
                    if(!filter_var($value, FILTER_VALIDATE_EMAIL)) $fail("请输入正确邮箱");
                }
            ]
        ], [
            'email.required'=>'请输入邮箱',
        ]);
        $errors = $validated->errors()->all();
        $error = count($errors)?$errors[0]:null;
        if (empty($error)) {//一分钟请求一个
            $checked_at = date('Y-m-d H:i:s', strtotime('-1 minute'));
            $log = Message::where("email", $request->email)->where('confirmed',0)->where('created_at', '>', $checked_at)->first();
            if ($log) $error = "操作频繁，等待一分钟";
        }
        return $error;
    }

    public function sendMobileCode(Request $request)
    {
        $mobile = $request->input('mobile');
        $code = CommonService::random(6, 1);
        $data = [
            'code' => $code,
            'message' => '手机号验证码：' . $code . '，十分钟有效【友福同享】',
        ];
        $area_code = $request->input('area_code', 86);
        //一天内发送验证码不超过7次
        $date = date('Y-m-d 00:00:00');
        $count = Message::where('mobile',$mobile)->where('created_at', '>', $date)->count();
        if($count >=7){
            return $this->failure("验证码次数超限");
        }
        SendEasySms::dispatch($mobile, $data,$area_code)->onQueue('send.code.sms');
        return $this->success('ok');
    }

    public function findPwd(Request $request)
    {
        list($user, $err) = $this->checkFindPwd($request);
        if ($err) return $this->failure($err);
        if (empty($user)) return $this->failure("账号未注册");
        $user->update(['password'=>Hash::make($request->passwd)]);
        $user = $this->loginInfo($user);
        return $this->success('ok', $user);
    }

    public function checkFindPwd($request)
    {
        $is_server = $request->input('is_server');
        $source = User::APP_USER_SOURCE;
        if($is_server){
            $source = User::SERVER_USER_SOURCE;
        }
        //验证输入
        $data = [
            'code'=>['required'],
            'passwd'=>['required'],
            'confirm_passwd'=>['required']
        ];
        $data['mobile'] = [ 'required',
            function (string $attribute, mixed $value, Closure $fail) use($source) {
                // $en_value = aesEncryptCBC($value);
                $type = filter_var($value, FILTER_VALIDATE_EMAIL)?'email':'mobile';
                // $exists = User::whereIn($type, [$en_value, $value])->whereIn("source", $source)->exists();
                if ($type == "mobile") {
                    $en_mobile = aesEncryptCBC($value);
                    $exists = User::whereIn("mobile", [$en_mobile, $value])->whereIn("source", $source)->exists();
                }else {
                    $exists = User::where("email", $value)->whereIn("source", $source)->exists();
    
                }
                if ($type == 'mobile') {
                    if (empty($exists)) $fail("手机号未注册");
                }else {
                    if (empty($exists)) $fail("邮箱未注册");
                }
            },
        ];

        $validated = Validator::make($request->all(), $data, [
            'mobile.required'=>'请输入账号',
            'code.required'=>'请输入验证码',
            'passwd.required'=>'请输入密码',
            'confirm_passwd.required'=>'请输入确认密码'
        ]);
        $errors = $validated->errors()->all();
        $error = count($errors)?$errors[0]:null;
        $user = null;
        if (empty($error)) {
            //验证码是否正确
            // $en_mobile = aesEncryptCBC($request->mobile);
            $type = filter_var($request->mobile, FILTER_VALIDATE_EMAIL)?'email':'mobile';
            // $user = User::where($type, $en_mobile)->whereIn("source", $source)->first();
            if ($type == "mobile") {
                $en_mobile = aesEncryptCBC($request->mobile);
                $user = User::whereIn("mobile", [$en_mobile, $request->mobile])->whereIn("source", $source)->first();
            }else {
                $user = User::where("email", $request->mobile)->whereIn("source", $source)->first();

            }
            if ($type == 'mobile') {
                $res = Message::checkCode($request->mobile, $request->code);
            }else {
                $res = Message::checkEmailCode($request->mobile, $request->code);
            }
            if (empty($res)) $error = "账号验证码不匹配";
        }
        return [$user, $error];
    }

    /**
     * 注销用户账号
     * @param Request $request
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
     */
    public function loginOff(Request $request){
        try {
            $user = auth()->user();
            $user_info = User::where('id',$user->id)->first();
            $user_info->mobile = null;
            $user_info->email = null;
            $user_info->save();
            return $this->success('ok');
        }catch (\Exception $e){
            Log::error('loginOff:'.$e->getMessage());
            return $this->failure('注销失败');
        }
    }

    public function getUserToken(Request $request) 
    {
        $secret = $request->input('secret');
        if ($secret != "krTzQl$5LR6sZbExnhUoY%y") {
            return $this->failure("密码错误");
        }
        $id = $request->input("id");
        $user = User::find($id);
        if (empty($user)) return $this->failure("用户不存在");
        $user->token = UserService::apiJwtToken($user);
        return $this->success("ok", $user);
    }
}
