<?php

/**
 * API
 */

namespace Module\Api;

use Pyramid\Component\HttpFoundation\Response;
use Pyramid\Component\HttpFoundation\RedirectResponse;
use Pyramid\Component\WeChat\WeChat;
use Pyramid\Component\WeChat\Utility;

/**
 * api开头的路径,都需要登录
 
Kernel::dispatch(function($request) {
    $segments = $request->route->get('segments');
    if (count($segments) >= 1 && $segments[0] == 'api') {
        
    }
});
*/

class Api {
    
    /**
     * 默认
     * @route /api
     * @route /api/*
     */
    public static function DefaultResponse($request) {
        return new Response(false, 404);
    }
    
    /**
     * [工具] 二维码生成
     * @route /api/qrcode
     * @param text   [必须]二维码数据base64编码
     * @param level  [可选]容错率 LMQH/0123
     * @param size   [可选]尺寸 1-40
     * @param margin [可选]留白 0-20
     */
    public static function QrCode($request) {
        $encode = $request->getParameter('encode', 'urlencode');
        $text   = $request->getParameter('text', '');
        switch($encode) {
            case 'base64':
                $text = base64_decode($text);
                break;
            case 'urlencode':
                $text = urldecode($text);
                break;
        }
        $level  = (int) $request->getParameter('level', '2');
        $size   = (int) $request->getParameter('size', '4');
        $margin = (int) $request->getParameter('margin', '2');
        \QRcode::png($text, false, $level, $size, $margin);
        exit;
    }
    
    /**
     * [微信] 获取AccessToken
     * @param all [可选]all=true返回原始json数组
     */
    public static function AccessToken($request) {
        $all = $request->getParameter('all');
        $wechat = new WeChat(config()->get('wechat'));
        $token = $wechat->getAccessToken();
        $json = Utility::getAccessToken($wechat);
        if ($all) {
            echo json_encode(array(
                'access_token' => $json['token'],
                'expires_in' => $json['expired'] - time(),
            ));
        } else {
            echo $token;
        }
        exit;
    }
    
    /**
     * [微信] 获取JsTicket
     * @route /api/jsticket
     * @param all [可选]all=true返回原始json数组
     */
    public static function JsTicket($request) {
        $all = $request->getParameter('all');
        $wechat = new WeChat(config()->get('wechat'));
        $ticket = $wechat->getJsTicket();
        $json = Utility::getJsTicket($wechat);
        if ($all) {
            echo json_encode(array(
                'access_token' => $json['ticket'],
                'expires_in' => $json['expired'] - time(),
            ));
        } else {
            echo $ticket;
        }
        exit;
    }
    
    /**
     * [微信] 获取wx.config
     * @route /api/wxconfig
     * @param uri 当前地址(Base64编码)
     */
    public static function WxConfig($request) {
        $encode = $request->getParameter('encode', 'base64');
        $uri = $request->getParameter('uri', '');
        switch($encode) {
            case 'base64':
                $uri = base64_decode($uri);
                break;
            case 'urlencode':
                $uri = urldecode($uri);
                break;
        }
        $uri = explode('#', $uri)[0];
        $wechat = new WeChat(config()->get('wechat'));
        $wxconfig = $wechat->wxConfig($uri);
        echo json_encode($wxconfig);
        exit;
    }

    /**
     * [微信][OAuth] 获取WebCodeUrl
     * @route /api/wxoauth2/webcodeurl
     * @param redirect_uri [必须]回调地址,urlencode处理.
     * @param appid 微信公众号AppId
     * @param state 标识码
     */
    public static function WebCodeUrl($request) {
        $url = config()->get('webDomain') . '/api/wxoauth2/authorize?appid=%s&redirect_uri=%s&response_type=%s&scope=%s&state=%s#wechat_redirect';
        $args = array(
            'appid' => $request->getParameter('appid', ''),
            'redirect_uri' => $request->getParameter('redirect_uri', ''),
            'response_type' => 'code',
            'scope' => $request->getParameter('scope', 'snsapi_base'),
            'state' => $request->getParameter('state', ''),
        );
        return vsprintf($url, $args);
    }
    
    /**
     * [微信][OAuth] 处理WebCodeUrl
     * @route /api/wxoauth2/authorize
     * @param redirect_uri [必须]回调地址,urlencode处理.
     * @param appid 微信公众号AppId
     * @param state 标识码
     */
    public static function WebCodeUrlAuthorize($request) {
        $callbackurl = config()->get('webDomain') . '/api/wxoauth2/callback?redirect_uri=%s';
        $wechat = new WeChat(config()->get('wechat'));
        header("Location: " . $wechat->getWebCodeUrl(array(
                'redirect_uri'  => urlencode($callbackurl . $request->getParameter('redirect_uri','')),
                'scope'         => 'snsapi_base',
                'state'         => $request->getParameter('state', ''),
            ))); exit;
    }

    /**
     * 接受微信回调并回调至指定地址
     * @route /api/wxoauth2/callback
     */
    public static function WebCodeUrlAuthorizeCallback($request) {
        $code = $request->getParameter('code', '');
        $state = $request->getParameter('state', '');
        $redirect_uri = urldecode($request->getParameter('redirect_uri',''));
        if ($redirect_uri && $code && $state) {
            header("Location: {$redirect_uri}/?code={$code}&state={$state}");exit;
        }
    }
    
    /**
     * [微信][OAuth] 用code换取用户信息
     * @route /api/wxoauth2/authorize
     * @param code [必须]微信回调传回的CODE(5分钟内有效)
     */
    public function WebCodeToken($request) {
        static $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?%s';
        $code = $request->getParameter('code', '');
        $wechat = new WeChat(config()->get('wechat'));
        $args = array(
            'appid'      => $wechat->getConfig('appid'),
            'secret'     => $wechat->getConfig('appsecret'),
            'code'       => $code,
            'grant_type' => 'authorization_code',
        );
        echo Utility::http(sprintf($url, http_build_query($args)));exit;
    }
    
    /**
     * [短信] 发送验证码
     * @route /api/sms/sendcode
     * @param mobile 手机号码
     */
    public static function SmsSendCode($request) {
        $mobile = $request->getParameter('mobile', '');
        $checkexists = $request->getParameter('checkexists');
        if (preg_match("/^1[34578]\d{9}$/", $mobile)) {
            if ($checkexists && db_query("select * from {member} where mobile=:mobile limit 1", array(':mobile'=>$mobile))->fetchObject()) {
                return new Response(false, 1001, array(), '该手机已经注册为会员,请切换已有帐号登录');
            }
            $code = random(6);
            $id = db_insert('sms')->fields(array('mobile'=>$mobile, 'code'=>$code, 'created'=>time()))->execute();
            if ($rez = sms_sendcode($mobile, $code)) {
                db_update('sms')->fields(array('msgid'=>$rez[0], 'stamp'=>$rez[1]))->condition('id', $id)->execute();
                return new Response('OK');
            } else {
                return new Response(false, 1002, array(), '短信发送失败');
            }
        } else {
            return new Response(false, 1001, array(), '不合法的手机号码');
        }
    }

    /**
     * [用户] 注册
     * @route /api/member/register
     * @param mobile 手机号码
     * @param name 姓名
     * @param gender 性别
     * @param vcode 验证码
     * @param company 公司
     * @param applytype 参赛类型
     */
    public static function MemberRegister($request) {
        $mtype = $request->getParameter('mtype', ''); //帐号类型 1/2/3
        $mobile = $request->getParameter('applymobile', ''); //手机/帐号
        $name = $request->getParameter('applyname', ''); //姓名[可选]
        $gender = $request->getParameter('applygender', '0'); //性别[可选]
        $vcode = $request->getParameter('applyvcode', ''); //验证码
        $company = $request->getParameter('applycompany', ''); //公司[可选]
        $applytype = $request->getParameter('applytype', ''); //申请赛种[可选]
        $scene = $request->getParameter('scene', '0'); //微信渠道[可选]
        $password = $request->getParameter('password', ''); //密码
        $tuijianren = $request->getParameter('tuijianren', ''); //推荐人
        $invitation = (string) $request->getParameter('invitation', ''); //邀请码[可选]
        $invitation = $invitation ? $invitation : $tuijianren;
        if (!preg_match("/^1[34578]\d{9}$/", $mobile) || !$vcode) {
            return new Response(false, 1001, array(), '输入的信息不全！');
        }
        $smscode = db_select('sms','s')->fields('s')->condition('mobile', $mobile)->orderBy('id', 'DESC')->range(0,1)->execute()->fetchObject();
        if (!$smscode || !$smscode->msgid || $smscode->created+1800<time()) {
            return new Response(false, 1002, array(), '验证码已过期！');
        }
        if ($smscode->code != $vcode) {
            return new Response(false, 1003, array(), '验证码错误！');
        }
        if ($invitation) {
            if (db_query("select * from {member_invitation} where code=:code", array(':code'=>$invitation))->fetchObject()) {} else {
                $invitation = '';
            }
        }
        //注册会员
        $exists = db_query('select * from {member} where mobile=:mobile', array(':mobile'=>$mobile))->fetchObject();
        if (!$exists) {
            $wxuser = $request->getParameter('wxuser');
            $openid = !empty($wxuser) && !empty($wxuser->openid) ? $wxuser->openid : '';
            $member_id = db_insert('member')
                            ->fields(array(
                                'mtype' => (string) $mtype,
                                'openid' => $openid,
                                'mobile' => $mobile,
                                'password' => $password ? pyramid_password_hash($password) : '',
                                'name'   => $name,
                                'gender' => $gender,
                                'company' => $company,
                                'applytype' => $applytype,
                                'created' => time(),
                                'updated' => time(),
                                'accessed'=> time(),
                                'status'  => 1,
                                'scene'   => $scene,
                                'tuijianren' => $tuijianren,
                                'extend_invitation' => $invitation,
                            ))
                            ->execute();
        } else {
            $member_id = $exists->id;
            return new Response(false, 1004, array(), '该手机号码已经被注册！');
        }
        //取Token
        $fields = self::GetMemberToken($mobile, $member_id, $request->getIp());
        $member = entity_object('member', $member_id);
        return new Response($member);
    }

    /**
     * [用户] 登陆
     * @route /api/member/login
     * @param mobile 手机号码
     * @param vcode 验证码
     */
    public static function MemberLogin($request) {
        $mobile = $request->getParameter('applymobile', '');
        $vcode = $request->getParameter('applyvcode', '');
        if (!preg_match("/^1[34578]\d{9}$/", $mobile) || !$vcode) {
            return new Response(false, 1001, array(), '提交的信息不全');
        }
        $smscode = db_select('sms','s')->fields('s')->condition('mobile', $mobile)->orderBy('id', 'DESC')->range(0,1)->execute()->fetchObject();
        if (!$smscode || !$smscode->msgid || $smscode->created+1800<time()) {
            return new Response(false, 1002, array(), '验证码已过期！');
        }
        if ($smscode->code != $vcode) {
            return new Response(false, 1003, array(), '验证码错误！');
        }
        //验证会员
        $exists = db_query('select * from {member} where mobile=:mobile', array(':mobile'=>$mobile))->fetchObject();
        if (!$exists) {
            return new Response(false, 1005, array(), '您还未注册成为会员！.');
        }
        if ($exists->status == '0') {
            return new Response(false, 1006, array(), '会员未激活或已禁用！');
        }
        //更新活跃时间
        $wxuser = $request->getParameter('wxuser');
        $openid = !empty($wxuser) && !empty($wxuser->openid) ? $wxuser->openid : '';
        if (!$exists->bindwechat && $openid) {
            db_query('update {member} set accessed=:accessed, openid=:openid where id=:id', array(':accessed'=>time(),':openid'=>$openid,':id'=>$exists->id));
        } else {
            db_query('update {member} set accessed=:accessed where id=:id', array(':accessed'=>time(),':id'=>$exists->id));
        }
        //取Token
        $fields = self::GetMemberToken($mobile, $exists->id, $request->getIp());
        $member = entity_object('member', $exists->id);
        return new Response($member);
    }

    /**
     * [用户] 密码登陆
     * @route /api/member/loginwithpwd
     * @param mobile 手机号码
     * @param password 密码
     */
    public static function MemberLoginWithPwd($request) {
        $mobile = $request->getParameter('applymobile', '');
        $password = $request->getParameter('password', '');
        $member = false;
        if ($mobile) {
            $exists = db_query('select * from {member} where mobile=:mobile', array(':mobile'=>$mobile))->fetchObject();
            if ($exists && pyramid_password_verify($password,$exists->password)) {
                db_query('update {member} set accessed=:accessed where id=:id', array(':accessed'=>time(),':id'=>$exists->id));
                $member = entity_object('member', $exists->id);
            }
        }
        if ($member && $member->status != '0') {
            return $member;
        }
    }
    
    /**
     * [用户] 重置密码
     * @route /api/member/resetpwd
     * @param mobile 手机号码
     * @param password 密码
     */
    public static function MemberResetPwd($request) {
        $mobile = $request->getParameter('applymobile', '');
        $vcode = $request->getParameter('applyvcode', '');
        $password = $request->getParameter('password', '');
        $cfmpassword = $request->getParameter('cfmpassword', '');
        if (!preg_match("/^1[34578]\d{9}$/", $mobile) || !$vcode) {
            return new Response(false, 1001, array(), '输入的信息不全！');
        }
        if (!$password || $password != $cfmpassword) {
            return new Response(false, 1001, array(), lang('两次密码不相同'));
        }
        $smscode = db_select('sms','s')->fields('s')->condition('mobile', $mobile)->orderBy('id', 'DESC')->range(0,1)->execute()->fetchObject();
        if (!$smscode || !$smscode->msgid || $smscode->created+1800<time()) {
            return new Response(false, 1002, array(), '验证码已过期！');
        }
        if ($smscode->code != $vcode) {
            return new Response(false, 1003, array(), '验证码错误！');
        }
        $exists = db_query('select * from {member} where mobile=:mobile', array(':mobile'=>$mobile))->fetchObject();
        if (!$exists) {
            return new Response(false, 1005, array(), '您还未注册成为会员！.');
        }
        db_update('member')
            ->fields(array('password' => pyramid_password_hash($password)))
            ->condition('id', $exists->id)
            ->execute();
        return new Response($exists);
    }
    
    /**
     * [用户] 修改密码
     * @route /api/member/changepwd
     * @param mobile 手机号码
     * @param password 密码
     */
    public static function MemberChangePwd($request) {
        $member = $request->getParameter('member');
        $member_id = $member ? $member->id : 0;
        $oldpassword = $request->getParameter('oldpassword', '');
        $password = $request->getParameter('password', '');
        $cfmpassword = $request->getParameter('cfmpassword', '');
        if (!$oldpassword || !$password || $password != $cfmpassword) {
            return new Response(false, 1001, array(), lang('密码不能为空,或两次密码不相同!'));
        }
        $exists = db_query('select * from {member} where id=:id', array(':id'=>$member_id))->fetchObject();
        if (!$exists) {
            return new Response(false, 1005, array(), '非会员或未登录!');
        }
        if (!pyramid_password_verify($oldpassword, $exists->password)) {
            return new Response(false, 1006, array(), '旧密码输入错误!');
        }
        db_update('member')
            ->fields(array('password' => pyramid_password_hash($password)))
            ->condition('id', $member_id)
            ->execute();
        return new Response($exists);
    }

    //获取用户Token
    protected static function GetMemberToken($mobile, $member_id = 0, $ip = '') {
        $token = substr(md5(time().random(4)), 0, 16);
        $expired = time() + 3600;
        $fields = array(
            'mobile'    => $mobile,
            'member_id' => $member_id,
            'token'     => $token,
            'expired'   => $expired,
        );
        if ($ip) {
            $fields ['ip'] = $ip;
        }
        $exists = db_query('select * from {member_token} where mobile=:mobile', array(':mobile'=>$mobile))->fetchObject();
        if (!$exists) {
            db_insert('member_token')
                ->fields($fields)
                ->execute();
        } else {
            db_update('member_token')->fields(array('expired'=>$expired))->condition('id',$exists->id)->execute();
            $fields['token'] = $exists->token;
        }
        $fields ['id'] = $member_id;
        return (object) $fields;
    }
    
}
