package com.crm.manager.controller;

import com.crm.login.rely.backend.controller.BaseLoginController;
import com.crm.manager.service.UserInfoService;
import com.crm.manager.service.UserRoleService;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.PrefixEnum;
import com.crm.rely.backend.core.constant.RegexpConstants;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.BaseResultWithPagerDto;
import com.crm.rely.backend.core.dto.user.info.*;
import com.crm.rely.backend.core.dto.user.role.UserNodeDisplayDto;
import com.crm.rely.backend.core.entity.base.SingleLongEntity;
import com.crm.rely.backend.core.entity.custom.info.IbInfoEntity;
import com.crm.rely.backend.core.entity.custom.info.InfoEntity;
import com.crm.rely.backend.core.entity.user.info.*;
import com.crm.rely.backend.core.enums.SalesType;
import com.crm.rely.backend.core.pojo.table.UserInfoTable;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.service.BlackListLoginService;
import com.crm.rely.backend.service.RedisService;
import com.crm.rely.backend.service.SysCountryService;
import com.crm.rely.backend.util.DateUtil;
import com.crm.rely.backend.util.GetIpAndMac;
import com.crm.rely.backend.util.HttpServletRequestUtil;
import com.crm.rely.backend.util.MD5Util;
import com.google.common.base.Strings;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static java.util.regex.Pattern.matches;

/**
 * @program: crm-backend
 * @description:
 * @author: houn
 * @create: 2019-07-25 15:57
 */
@Log4j
@RestController
@RequestMapping("/user")
public class UserController extends BaseLoginController {

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private BlackListLoginService blackListLoginService;

    @Autowired
    private SysCountryService sysCountryService;

    @Autowired
    private RedisService redisService;

    @PostMapping("/login/valid")
    public BaseResultDto loginValid(@RequestBody @Validated UserLoginValidEntity entity, HttpServletRequest request) throws Exception {

        log.info(String.format("login request,username:%s,time:%s",
                entity.getLoginName().toLowerCase(), DateUtil.formatTime()));

        blackListLoginService.validate(PrefixEnum.PREFIX_USER.getCode() + entity.getLoginName().toLowerCase(),
                PrefixEnum.PREFIX_USER.getCode(), "127.0.0.1");
        //密码处理为
        entity.setPassword(MD5Util.getMD5(entity.getPassword()));

        Integer valid = userInfoService.loginValid(entity);

        redisService.save(entity.getLoginName().toLowerCase() + entity.getPassword() + "loginValid", 1, 5 * 60 * 1000);

        return BaseResultDto.success(Constants.SUCCESS, valid);
    }

    /**
     * 登录信息
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/login")
    public BaseResultDto login(@RequestBody @Validated UserLoginEntity entity, HttpServletRequest request) throws Exception {

        //密码处理为
        entity.setPassword(MD5Util.getMD5(entity.getPassword()));

        if (!redisService.hasKey(entity.getLoginName().toLowerCase() + entity.getPassword() + "loginValid")) {
            blackListLoginService.validate(PrefixEnum.PREFIX_USER.getCode() + entity.getLoginName().toLowerCase(),
                    PrefixEnum.PREFIX_USER.getCode(), "127.0.0.1");
        }

        log.info(String.format("login request,username:%s,time:%s",
                entity.getLoginName().toLowerCase(), DateUtil.formatTime()));


        /**
         * 处理登录时间 登录ip 登录地区
         */
        entity.setIp(GetIpAndMac.getIp(request));
        String returnStr = sysCountryService.getAdderByIp(entity.getIp());

        entity.setAddress(returnStr);
        entity.setTime(new Date());

        InfoEntity userInfoEntity = userInfoService.login(entity);

        String accessToken = super.login(userInfoEntity);

        return BaseResultDto.success(Constants.LOGIN_SUCCESS, accessToken);
    }

    @PostMapping("/attachs")
    public BaseResultDto<List<UserAttachInfoDto>> getAttachs(InfoEntity infoEntity) throws ServiceException{
        List<UserAttachInfoDto> userAttachInfo = userInfoService.getUserAttachInfo(infoEntity);
        return BaseResultDto.success(userAttachInfo);
    }

    @PostMapping("/switchLogin")
    public BaseResultDto switchLogin(@RequestBody @Validated UserAttachLoginEntity entity, HttpServletRequest request, InfoEntity infoEntity) throws Exception {

        if (!entity.getAttachId().equals(infoEntity.getIbInfo().getAttachId())) {
            return BaseResultDto.error(Constants.NOT_PERMIT);
        }
        /**
         * 处理登录时间 登录ip 登录地区
         */
        entity.setIp(GetIpAndMac.getIp(request));
        String returnStr = sysCountryService.getAdderByIp(entity.getIp());

        entity.setAddress(returnStr);
        entity.setTime(new Date());
        entity.setUserId(infoEntity.getIbInfo().getId());
        //当前用户登录
        super.logout(request);
        //登录关联用户
        InfoEntity userInfoEntity = userInfoService.loginByAttachId(entity);
        String accessToken = super.login(userInfoEntity);

        return BaseResultDto.success(Constants.LOGIN_SUCCESS, accessToken);
    }

    @PostMapping("/google/secretKey")
    public BaseResultDto userGoogleSecretKey(InfoEntity infoEntity) throws Exception {
        if (infoEntity.getVerified() != null & 1 == infoEntity.getVerified()) {
            return BaseResultDto.error(Constants.GOOGLE_SECRET_BIND_ERROR);
        }
        UserInfoGoogleSecretKeyDto googleSecretKeyDto = userInfoService.getGoogleSecretKey(infoEntity.getId());
        if (!googleSecretKeyDto.getSecretKey().equals(infoEntity.getSecretKey())) {

            infoEntity.setSecretKey(googleSecretKeyDto.getSecretKey());
            saveLoginInfo(infoEntity);
        }
        return BaseResultDto.success(googleSecretKeyDto);
    }

    @PostMapping("/get/google/secretKey")
    public BaseResultDto getGoogleSecretKey(@RequestBody SingleLongEntity entity) throws ServiceException {

        UserInfoGoogleSecretKeyDto googleSecretKeyDto = userInfoService.getGoogleSecretKey(entity.getId());
        return BaseResultDto.success(googleSecretKeyDto);
    }

    /**
     * 绑定谷歌验证码
     *
     * @param entity
     * @throws ServiceException
     */
    @PostMapping("/bind")
    public BaseResultDto bind(@RequestBody @Validated UserInfoBindEntity entity, InfoEntity infoEntity) throws Exception {
        entity.setId(infoEntity.getId());

        userInfoService.bind(entity);
        infoEntity.setVerified(1);
        saveLoginInfo(infoEntity);

        return BaseResultDto.success();
    }

    /**
     * 清理谷歌密钥 但不解除绑定
     *
     * @param
     * @throws ServiceException
     */

    @PostMapping("/close/secret/key")
    public BaseResultDto closeSecretKey(@RequestBody @Validated SingleLongEntity entity) throws ServiceException {
        userInfoService.closeSecretKey(entity.getId());

        return BaseResultDto.success();
    }

    /**
     * 重置密钥 后续重新绑定
     *
     * @param
     * @throws ServiceException
     */

    @PostMapping("/re/secret/key")
    public BaseResultDto reSecretKey(@RequestBody @Validated SingleLongEntity entity) throws ServiceException {
        userInfoService.reSecretKey(entity.getId());

        return BaseResultDto.success();
    }

    @PostMapping("/login/send/code")
    public BaseResultDto loginSendCode(@RequestBody @Validated UserLoginSendEmailCodeEntity entity) throws ServiceException {

        userInfoService.loginSendCode(entity);

        return BaseResultDto.success();
    }

    /**
     * 退出登录
     *
     * @param httpServletRequest
     * @throws Exception
     */
    @Override
    @PostMapping("/logout")
    public BaseResultDto logout(HttpServletRequest httpServletRequest) throws Exception {

        return super.logout(httpServletRequest);
    }

    /**
     * 获取登录信息
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/info")
    public BaseResultDto info(InfoEntity entity) throws Exception {

        UserInfoDto userInfoDto = new UserInfoDto();
        if(entity.getIbInfo().getRoleId() == null){
            userInfoDto.setIsAdmin(1);
        }
        BeanUtils.copyProperties(entity.getIbInfo(), userInfoDto);
        userInfoDto.setVerified(entity.getVerified());
        Long roleId;
        if (PrefixEnum.PREFIX_SYSTEM.equals(entity.getPrefix())) {
            roleId = 0L;
        } else {
            roleId = entity.getIbInfo().getRoleId();
        }
        List<UserNodeDisplayDto> userNodeDisplayDtos = userRoleService.getUserNodeDisplay(roleId);
        userInfoDto.setDisplay(userNodeDisplayDtos);

        return BaseResultDto.success(userInfoDto);
    }

    @PostMapping("/display/{roleId}")
    public String getUserNodeDisplay(@PathVariable("roleId") Long roleId) throws Exception {
        userRoleService.getUserNodeDisplay(roleId);
        return "success";
    }

    /**
     * 添加用户
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/add")
    public BaseResultDto add(@RequestBody @Validated UserInfoAddEntity entity) throws Exception {
        entity.setEmail(entity.getEmail().toLowerCase());
        //密码
        entity.setPassword(MD5Util.getMD5(entity.getPassword()));
        if (entity.getCommissionApproval() == null) {
            entity.setCommissionApproval(0);
        }
        if (entity.getIpLimit() == null) {
            entity.setIpLimit(0);
        }
        if (entity.getHide() == null) {
            entity.setHide(0);
        }
        //如果登录名不填 默认为邮箱
        if (Strings.isNullOrEmpty(entity.getUsername())) {
            entity.setUsername(entity.getEmail());
        }

        //如果不填是否禁用 默认为1 可以登录
        if (entity.getValid() == null) {
            entity.setValid(1);
        }

        if (entity.getSalesType() == null) {
            entity.setSalesType(SalesType.COMMON_SALES.getCode());
        }
        userInfoService.add(entity);

        return BaseResultDto.success(Constants.ADD_SUCCESS);
    }

    /**
     * 删除用户信息
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/delete")
    public BaseResultDto delete(@RequestBody @Validated UserInfoDeleteEntity entity) throws Exception {

        userInfoService.delete(entity);

        return BaseResultDto.success(Constants.DELETE_SUCCESS);
    }

    /**
     * 修改用户信息
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/update")
    public BaseResultDto update(@RequestBody @Validated UserInfoUpdateEntity entity) throws Exception {
        entity.setEmail(entity.getEmail().toLowerCase());
        if (entity.getHide() == null) {
            entity.setHide(0);
        }
        if (entity.getCommissionApproval() == null) {
            entity.setCommissionApproval(0);
        }
        if (entity.getIpLimit() == null) {
            entity.setIpLimit(0);
        }
        if (entity.getSalesType() == null) {
            entity.setSalesType(SalesType.COMMON_SALES.getCode());
        }
        //验证是否为空
        if (!Strings.isNullOrEmpty(entity.getPassword())) {

            //验证格式
            if (!matches(RegexpConstants.REGEXP_PWD, entity.getPassword())) {
                return BaseResultDto.error(Constants.PASSWORD_FORMAT_ERROR);
            }

            entity.setPassword(MD5Util.getMD5(entity.getPassword()));
        }
        UserInfoTable userInfoTable = userInfoTable = userInfoService.update(entity);


        //保存到redis
        PrefixEnum prefixEnum = userInfoService.getPrefixEnum(userInfoTable.getRoleId());

        //如果密码不为空 则在修改后吧redis中的客户信息置空(退出登录)
        if (!Strings.isNullOrEmpty(entity.getPassword()) || entity.getValid() == null || entity.getValid() == 0) {
            logout(prefixEnum, userInfoTable.getId());
        }
        try {
            InfoEntity infoEntity = getLoginInfo(prefixEnum, userInfoTable.getId(), InfoEntity.class);
            //如果redis没有记录 则不用更新
            if (infoEntity != null) {
                IbInfoEntity userInfoEntity = infoEntity.getIbInfo();
                infoEntity.setValid(userInfoTable.getValid() == null ? 0 : userInfoTable.getValid());
                BeanUtils.copyProperties(userInfoTable, userInfoEntity);
                infoEntity.setIbInfo(userInfoEntity);
                saveLoginInfo(infoEntity);
            }
        } catch (Exception e) {
            redisService.remove(prefixEnum.getCode() + userInfoTable.getId());
        }


        return BaseResultDto.success();
    }

    /**
     * 查询用户 page
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/search/page")
    public BaseResultDto searchPage(@RequestBody @Validated UserInfoSearchEntity entity,InfoEntity infoEntity) throws Exception {
        if (entity.getEndDate() != null) {
            entity.setEndDate(DateUtil.operationDay(entity.getEndDate(), 1));
        }
        if (entity.getStartDate() != null) {
            entity.setStartDate(DateUtil.parseDate(entity.getStartDate()));
        }
        if(infoEntity.getIbInfo().getMerchantId() != null){
            entity.setMerchantId(infoEntity.getIbInfo().getMerchantId());
        }
        BaseResultWithPagerDto resultWithPagerDto = userInfoService.searchPage(entity);

        return resultWithPagerDto;
    }

    /**
     * 单个查询
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/search/single")
    public BaseResultDto searchSingle(@RequestBody @Validated SingleLongEntity entity) throws Exception {

        UserInfoSearchDto userInfoSearchDto = userInfoService.searchSingle(entity.getId());

        return BaseResultDto.success(Constants.SEARCH_SUCCESS, userInfoSearchDto);
    }

    @PostMapping("/search/ib/single")
    public BaseResultDto searchIbSingle(@RequestBody @Validated UserInfoIbSearchEntity entity) throws Exception {

        UserInfoIbNoDto userInfoSearchDto = userInfoService.searchIbSingle(entity);

        return BaseResultDto.success(Constants.SEARCH_SUCCESS, userInfoSearchDto);
    }

    @PostMapping("/search/info")
    public UserStaticDto searchInfo() throws Exception {
        return userInfoService.getStaticData();
    }

    @PostMapping("/switch/lang")
    public BaseResultDto switchLang(@RequestBody @Validated UserInfoSwitchLangEntity entity,
                                    HttpServletRequest request, HttpServletResponse response) throws Exception {
        InfoEntity infoEntity = HttpServletRequestUtil.getLoginInfo(InfoEntity.class, request, redisService, true);
        if (infoEntity == null || infoEntity.getIbInfo() == null) {
            //构建修改语言实体
            UserInfoUpdateLangEntity userInfoUpdateLangEntity = new UserInfoUpdateLangEntity();
            userInfoUpdateLangEntity.setId(infoEntity.getIbInfo().getId());
            userInfoUpdateLangEntity.setModifyIp(GetIpAndMac.getIp(request));
            userInfoUpdateLangEntity.setModifyTime(new Date());
            userInfoUpdateLangEntity.setModifyUser(infoEntity.getIbInfo().getId());
            userInfoUpdateLangEntity.setLang(entity.getLang());
            userInfoService.updateLang(userInfoUpdateLangEntity);

            //修改语言
            infoEntity.setLang(entity.getLang());

            saveLoginInfo(infoEntity);
        }

        setLocaleResolver(entity.getLang(), request, response);

        return BaseResultDto.success();
    }

    /**
     * 未登录修改密码发送邮件
     *
     * @param entity
     * @param req
     * @return
     */
    @PostMapping("/update/password/send/email")
    public BaseResultDto updatePasswordSendEmail(@RequestBody @Validated UserUpdatePasswordSendEmailEntity entity,
                                                 HttpServletRequest req) throws Exception {


        entity.setIp(GetIpAndMac.getIp(req));
        entity.setTime(new Date());
        userInfoService.updatePasswordSendEmail(entity);

        return BaseResultDto.success(Constants.SEND_SUCCESS);
    }

    /**
     * 未登录根据邮件修改密码
     *
     * @param entity
     * @param req
     * @return
     */
    @PostMapping("/update/email/password")
    public BaseResultDto updatePassword(@RequestBody @Validated UserUpdateEmailPasswordEntity entity,
                                        HttpServletRequest req) throws Exception {

        entity.setModifyIp(GetIpAndMac.getIp(req));
        entity.setModifyTime(new Date());
        entity.setPassword(MD5Util.getMD5(entity.getPassword()));

        userInfoService.updatePassword(entity);

        return BaseResultDto.success(Constants.SUCCESS);
    }

    @PostMapping("/update/login/password")
    public BaseResultDto updatePassword(@RequestBody @Validated UserUpdateLoginPasswordEntity entity,
                                        HttpServletRequest req, InfoEntity infoEntity) throws Exception {

        entity.setId(infoEntity.getIbInfo().getId());
        if (entity.getNewPassword().equals(entity.getOldPassword())) {
            return BaseResultDto.error(Constants.PASSWORD_NEW_AND_OLD_IDENTICAL_ERROR);
        }

        entity.setModifyIp(GetIpAndMac.getIp(req));
        entity.setModifyTime(new Date());
        entity.setModifyUser(infoEntity.getId());
        entity.setNewPassword(MD5Util.getMD5(entity.getNewPassword()));
        entity.setOldPassword(MD5Util.getMD5(entity.getOldPassword()));

        userInfoService.updatePassword(entity);
        return BaseResultDto.success(Constants.UPDATE_SUCCESS);
    }

    private void setLocaleResolver(String lang, HttpServletRequest request, HttpServletResponse response) {
        LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
        try {
            if ("cn".equals(lang)) {
                localeResolver.setLocale(request, response, new Locale("zh", "CN"));
            } else {
                localeResolver.setLocale(request, response, new Locale("en", "US"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PostMapping("/sales")
    public BaseResultDto<List<SalesInfoDropdownDto>> salesInfoDropdown() throws Exception {
        return userInfoService.getSalesInfoDropdown();
    }

    /**
     * 账号解封
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/unseal")
    public BaseResultDto unseal(@RequestBody @Validated UserInfoUnsealEntity entity) throws Exception {
        blackListLoginService.removeFromList(PrefixEnum.PREFIX_USER.getCode() + entity.getLoginName().toLowerCase(),
                PrefixEnum.PREFIX_USER.getCode());
        return BaseResultDto.success();
    }

    /**
     * 检查账号是否被封
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/check/seal")
    public BaseResultDto checkSeal(@RequestBody @Validated UserInfoCheckSealEntity entity) throws Exception {
        boolean checkSealBool =
                blackListLoginService.checkSeal(PrefixEnum.PREFIX_USER.getCode() + entity.getLoginName().toLowerCase());
        return BaseResultDto.success(checkSealBool);
    }


    @PostMapping("/sales/tree")
    public BaseResultDto<UserInfoTreeDto> salesTree() throws Exception {
        return BaseResultDto.success(userInfoService.getUserInfoTree());
    }


    @GetMapping("/j6clzdw076f34ve07qo")
    public String initIdStamp() throws Exception {
        try {
            userInfoService.initIdStamp();
            return Constants.SUCCESS;
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    /**
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/search/entry/list")
    public BaseResultDto getEntryUserList(@RequestBody UserInfoEntrySearchEntity entity) throws Exception {
        BaseResultWithPagerDto resultWithPagerDto = userInfoService.getEntryUserList(entity);
        return resultWithPagerDto;
    }

    /**
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/search/list")
    public BaseResultDto getUserList(@RequestBody UserInfoListEntity entity) throws Exception {

        return BaseResultDto.success(userInfoService.getUserList(entity));
    }

    /**
     * 重置密码
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/reset/password")
    public BaseResultDto resetPassword(@RequestBody @Validated UserResetPasswordEntity entity) throws Exception {

        return BaseResultDto.success(Constants.SUCCESS, userInfoService.resetPassword(entity));

    }

    /**
     * 查看销售信息
     *
     * @param entity
     * @return
     * @throws Exception
     */
    @PostMapping("/search/sales")
    public BaseResultDto getSalesInfo(@RequestBody @Validated UserInfoSalesSearchEntity entity, HttpServletRequest httpServletRequest) throws Exception {
        return BaseResultDto.success(userInfoService.getSalesInfo(entity));

    }

    @PostMapping("/update/show/login/type")
    public BaseResultDto managerUpdateExcludeShowLoginType(@RequestBody @Validated UserInfoUpdateExcludeShowLoginTypeEntity entity) throws Exception {
        userInfoService.updateExcludeShowLoginType(entity);
        return BaseResultDto.success();
    }

}
