package com.bofeng.controller;

import com.baomidou.mybatisplus.toolkit.IdWorker;
import com.bofeng.Consts;
import com.bofeng.JwtHelper;
import com.bofeng.entity.*;
import com.bofeng.service.*;
import com.google.common.base.Strings;
import com.yvan.Model;
import com.yvan.ModelOps;
import com.yvan.freemarker.RedirectViewJs;
import com.yvan.mvc.Pd;
import com.yvan.platform.Conv;
import com.yvan.springmvc.HttpUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@RestController
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private SecurityService securityService;

    @Autowired
    private WxMpService mpService;

    @Autowired
    private UserOpenService userOpenService;

    @Autowired
    private UserPlaceService userPlaceService;

    @Autowired
    private PlaceService placeService;

    @GetMapping("/user/logout.html")
    @PostMapping("/user/logout.html")
    public ModelAndView logout() {
        HttpUtils.removeCookie(JwtHelper.AUTH_COOKIE_NAME, "/");
        SecurityUtils.getSubject().logout();
        return new ModelAndView(new RedirectViewJs("/"));
    }

    @GetMapping("/user/login.html")
    public ModelAndView login() {
        return new ModelAndView("/user/login.ftl");
    }

    @PostMapping("/user/login.json")
    public Model<LoginResult> loginPost(HttpServletResponse response,
                                        HttpServletRequest request,
                                        @Pd(name = "ig_username") final String loginName,
                                        @Pd(name = "ig_password") final String loginPwd) {

        User user;
        try {
            user = userService.login(loginName);

            //校验密码
            String secretPwd = securityService.createPassword(user, loginPwd);
            if (!secretPwd.equals(user.getLoginPwd())) {
                throw new IncorrectCredentialsException();
            }

        } catch (Exception e) {
            return processException(e);
        }

        //生成 Auth
        String jwt = securityService.createJwt(user, false);

        //写入头部和cookie
        HttpUtils.currentResponse().addHeader(JwtHelper.AUTH_HEADER_NAME, jwt);

        //更新登录成功次数和日期
        userService.updateLoginCount(user.getUserId());

        //返回客户端
        LoginResult loginResult = new LoginResult();
        loginResult.setUser(user);
        loginResult.setToken(jwt);
        if (Consts.USER_TYPE_ADMIN.equals(user.getUserType())) {
            loginResult.setHref("/admin/index.html");
        } else if (Consts.USER_TYPE_CASHIER.equals(user.getUserType())) {
            loginResult.setHref("/cashier/customer_accounts.html");
        } else if (Consts.USER_TYPE_WORKER.equals(user.getUserType())) {
            loginResult.setHref("/worker/room_manage.html");
        }


        response.setHeader("Access-Control-Expose-Headers", JwtHelper.AUTH_HEADER_NAME);
        response.setHeader(JwtHelper.AUTH_HEADER_NAME, JwtHelper.getAuthHeader(request));

        return Model.newSuccess(loginResult).setMsg("登录成功");
    }

    @PostMapping("/user/reset_password.json")
    public ModelOps resetPassword(@RequestBody Map map) {
        String userId = JwtHelper.getUserId();
        if (Strings.isNullOrEmpty(userId)) {
            return ModelOps.newFail("用户不存在或登录已经过期");
        }
        if (Strings.isNullOrEmpty(Conv.NS(map.get("password")))) {
            return ModelOps.newFail("密码不能为空");
        }
        if (Strings.isNullOrEmpty(Conv.NS(map.get("newPassword")))) {
            return ModelOps.newFail("新密码不能为空");
        }
        if (!Conv.NS(map.get("newPassword")).equals(Conv.NS(map.get("repeatPassword")))) {
            return ModelOps.newFail("两次密码不一致");
        }
        int result = userService.updatePassword(Conv.NL(userId), Conv.NS(map.get("password")),Conv.NS(map.get("newPassword")));
        if (result<=0) {
            return ModelOps.newFail("修改失败");
        }
        HttpUtils.removeCookie(JwtHelper.AUTH_COOKIE_NAME, "/");
        SecurityUtils.getSubject().logout();
        return ModelOps.newSuccess(result).setMsg("密码修改成功，请重新登录");
    }

    private Model<LoginResult> processException(Exception e) {
        Model<LoginResult> r = new Model<LoginResult>().setSuccess(false);

        if (e instanceof UnknownAccountException) {
            return r.setMsg("登录账号不存在!");
        }
        if (e instanceof LockedAccountException) {
            return r.setMsg("用户已经被锁定不能登录，请与管理员联系！");
        }
        if (e instanceof DisabledAccountException) {
            return r.setMsg("用户已经被禁用，请与管理员联系！");
        }
        if (e instanceof ExcessiveAttemptsException) {
            return r.setMsg("登录失败次数过多！");
        }
        if (e instanceof ExpiredCredentialsException) {
            return r.setMsg("凭证过期！");
        }
        if (e instanceof IncorrectCredentialsException) {
            return r.setMsg("密码错误!");
        }
        if (e instanceof AuthenticationException) {
            return r.setMsg("用户或密码不正确！");
        }

        log.error("e", e);
        return r.setMsg("未知错误:" + e.getMessage());
    }

    @GetMapping("/cust/user_bind.html")
    public ModelAndView userBind(@RequestParam(name = "userType", required = false, defaultValue = "") String userType,
                                 @RequestParam(name = "higherId", required = false, defaultValue = "") String higherId,
                                 @RequestParam(name = "placeId", required = false, defaultValue = "") String placeId,
                                 @RequestParam(name = "code", required = false, defaultValue = "") String code,
                                 ModelMap model) throws WxErrorException {
        if (!Strings.isNullOrEmpty(code)) {
            WxMpOAuth2AccessToken accessToken = mpService.oauth2getAccessToken(code);
            WxMpUser wxMpUser = mpService.oauth2getUserInfo(accessToken, null);
//            model.put("user", user);
            UserOpen userOpen = userOpenService.getUserByOpenId(wxMpUser.getOpenId());
            UserPlace userPlace = null;
            User user = null;

            if (userOpen != null) {
                userPlace = userPlaceService.getByUserIdAndPlaceId(userOpen.getUserId(), Conv.NL(placeId));
                user = userService.getUserById(userOpen.getUserId());
                if (user != null) {
                    model.put("user", user);
                }

            }
            if (userPlace == null) {
                Place place = placeService.getById(Conv.NL(placeId));
                model.put("placeName", place.getPlaceName());
                model.put("placeId", placeId);
                model.put("userType", userType);
                model.put("higherId", higherId);
                model.put("openId", wxMpUser.getOpenId());
                model.put("nickName", wxMpUser.getNickname());
                model.put("sexDesc", wxMpUser.getSexDesc());
                model.put("sex", wxMpUser.getSex());
                model.put("city", wxMpUser.getCity());
                model.put("province", wxMpUser.getProvince());
                model.put("country", wxMpUser.getCountry());
                model.put("headImgUrl", wxMpUser.getHeadImgUrl());
                return new ModelAndView("/cust/user_bind.ftl", model);

            } else {
                model.put("title", "您已经绑定过账号了！");
                if (userPlace.getUserType().equals(Consts.USER_TYPE_L1)) {
                    model.put("message", "一级分销");
                } else if (userPlace.getUserType().equals(Consts.USER_TYPE_L2)) {
                    model.put("message", "二级分销");
                }
            }
            return new ModelAndView("/prompt/prompt.ftl", model);

        } else {
            User user = new User();
            user.setUserType("1");
            model.put("user", user);
            model.put("openId", "2345");
            return new ModelAndView("/cust/user_bind.ftl");

        }

    }

    @PostMapping("/admin/deleteOpenId.json")
    public ModelOps bindUser(@RequestParam("userId") Long userId) {
        return ModelOps.newSuccess(userService.deleteOpenId(userId));
    }

    @PostMapping("/cust/user_bind.json")
    public ModelOps bindUser(HttpServletResponse response,
                             HttpServletRequest request,
                             @RequestBody Map map) {


        UserOpen userOpen = userOpenService.getUserByOpenId((String) map.get("openId"));
        if (userOpen == null) {
            userOpen = new UserOpen();
            userOpen.setUserId(IdWorker.getId());
            userOpen.setBeActive("Y");
            userOpen.setOpenId((String) map.get("openId"));
            userOpen.setNickName((String) map.get("nickName"));
            userOpen.setSex(Integer.valueOf((String) map.get("sex")));
            userOpen.setSexDesc((String) map.get("sexDesc"));
            userOpen.setCity((String) map.get("city"));
            userOpen.setProvince((String) map.get("province"));
            userOpen.setCountry((String) map.get("country"));
            userOpen.setHeadImgUrl((String) map.get("headImgUrl"));
        }
        User user = userService.getUserById(userOpen.getUserId());
        UserPlace userPlace = userPlaceService.getByUserIdAndPlaceId(userOpen.getUserId(), Conv.NL(map.get("placeId")));
        if (user == null) {
            user = new User();
            user.setUserId(userOpen.getUserId());
            user.setBeActive("Y");
            user.setUserType("S");
            user.setStaffName((String) map.get("staffName"));
            user.setPhone((String) map.get("phone"));
            user.setLoginName("");
            user.setVersion("1.1");
//            return ModelOps.newSuccess(userOpenService.bindUserOpen(userOpen, user));
        }
        if (userPlace == null) {
            userPlace = new UserPlace();
            userPlace.setHigherId(Conv.NL(map.get("higherId")));
            userPlace.setPlaceId(Conv.NL(map.get("placeId")));
            userPlace.setUserId(userOpen.getUserId());
            userPlace.setUserType(Conv.NS(map.get("userType")));
        } else {

            return ModelOps.newFail("已经绑定");
        }

        return ModelOps.newSuccess(userOpenService.bindUser(userOpen, user, userPlace));

    }

}
