package cn.superdesk.uniorder.controller.sys;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.superdesk.uniorder.common.HttpClientUtils;
import cn.superdesk.uniorder.common.enums.common.CommonEnabledEnum;
import cn.superdesk.uniorder.common.enums.common.CommonSoftDeleteEnum;
import cn.superdesk.uniorder.common.enums.common.CommonSourceFromEnum;
import cn.superdesk.uniorder.common.exception.UnifiedOrderRuntimeException;
import cn.superdesk.uniorder.common.exception.utils.ExceptionUtils;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.numerical.AnConvertBeanUtil;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.common.rest.response.ResponseResultOuterUtils;
import cn.superdesk.uniorder.controller.base.BaseController;
import cn.superdesk.uniorder.dao.entity.organisation.SysCompany;
import cn.superdesk.uniorder.dao.entity.sys.SysUser;
import cn.superdesk.uniorder.dao.entity.sys.SysUserOrderSourcetypeKey;
import cn.superdesk.uniorder.dto.param.system.SysUserQueryCriteria;
import cn.superdesk.uniorder.dto.vo._superdeskapp.jwt.SupperdeskAppResponse;
import cn.superdesk.uniorder.dto.vo._superdeskapp.jwt.SupperdeskAppTokenUser;
import cn.superdesk.uniorder.dto.vo.sys.SysUserModify;
import cn.superdesk.uniorder.dto.vo.sys.SysUserView;
import cn.superdesk.uniorder.dto.vo.sys.SysUserVo;
import cn.superdesk.uniorder.dubbo.consumer.sys.SysUserDubboConsumerService;
import com.fasterxml.jackson.core.type.TypeReference;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.*;

@Api(value = "系统管理-系统用户", tags = {"系统管理-系统用户"})
@Slf4j
@RestController
@RequestMapping("/user")
public class SysUserController extends BaseController {


    @Autowired
    private SysUserDubboConsumerService sysUserDubboConsumerService;


    // unified.out.tokenurl=http://superdesk.avic-s.com/super_cloud/api/organisation/wechat/front/user/getVirAndUserInfo
    // unified.out.saleurl=http://superdesk.avic-s.com/super_cloud/api/organisation/wechat/front/merchant/findMerchantById
    @Value("${unified.out.tokenurl}")
    private String TOKENURL;

    /**
     * 登陆
     *
     * @param username
     * @param password
     * @return
     * @throws ServletException
     * @throws UnifiedOrderRuntimeException
     */
    @PostMapping("/login")
    @ResponseBody
    public R<SysUserVo> login(String username, String password, String localIp, String verificationCode,
                              HttpServletRequest request,
                              HttpSession session) throws ServletException, UnifiedOrderRuntimeException {

        log.info("params : \nusername:{}\npassword:{}\nlocalIp:{}\nverificationCode:{}\nsessionId:{}\n",
                username, password, localIp, verificationCode, session.getId()
        );

        R<SysUserVo> response = new R<>();

        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            response.setSuccess(false);
            response.setMessage("账号或密码为空。");
            return response;
        }

        if (StringUtils.isBlank(verificationCode)) {
            response.setSuccess(false);
            response.setMessage("请输入验证码");
            return response;
        }

//        if (StringUtils.isNotEmpty(verificationCode)) {
//
//            String sessionVerificationCode = "";
//
//            Object verificationCodeObj = session.getAttribute("verificationCode");
//
//            if (null != verificationCodeObj) {
//                sessionVerificationCode = verificationCodeObj.toString();
//            } else {
//                response.setSuccess(false);
//                response.setMessage("验证码已过期,请刷新后重试");
//                // response.setMessage("服务器 获取 验证码 失败, 前端没有携带之前的cookie信息, 请求请加上 withCredentials:true | " + sessionVerificationCode);
//                return response;
//            }
//
//            log.info("\nlogin\nsessionId:{}\nsessionVerificationCode:{}", session.getId(), sessionVerificationCode);
//
//            // 验证码使用一次就失效
//            session.setAttribute("verificationCode", "PQRSTUVWXYZ");
//
//            if (StringUtils.isNotEmpty(sessionVerificationCode)) {
//
//                if (!sessionVerificationCode.equalsIgnoreCase(verificationCode)) {
//
//                    response.setSuccess(false);
//                    response.setMessage("验证码输入错误");
//                    return response;
//                }
//            }
//        }

        SysUserVo user = sysUserDubboConsumerService.userLoginBySupperDeskUniOrderBackEndFacade(username, password);

        if (null == user) {
            response.setSuccess(false);
            response.setMessage("账号或密码输入错误");
            return response;
        }

        response.setData(user);

        // 记录登陆日志
        sysUserDubboConsumerService.createLog(user.getId(), request.getRemoteAddr(), localIp);

        return response;

    }

    //dz add 20190901 token登陆
    @PostMapping("/tokenlogin")
    @ResponseBody
    public R<SysUserVo> loginByToken(String token) throws ServletException, UnifiedOrderRuntimeException, IOException {

        R<SysUserVo> response = new R<>();

        if (StringUtils.isEmpty(token)) {
            response.setSuccess(false);
            response.setMessage("token 令牌为空");
            return response;
        }

        Map<String, String> params = new HashMap<>();
        params.put("userToken", token);

        // 请求服务之窗
        String responseJsonStr = HttpClientUtils.doPost(TOKENURL, params);

//		http://192.168.6.223:8282/#/login?token=64a927ae243535900589848e173359c8
//		responseJsonStr = FileUtil.readUtf8String("/Users/linjinyu/JAVA_HOME/workspace_superdesk/superdesk-uniorder/superdesk-uniorder-web/src/main/java/cn/superdesk/uniorder/controller/sys/yyds.json");


        /****************************************** 重构 mark by linjinyu at 20210615 start ******************************************/
//		Map jsonMap = JSON.parseObject(jsonstr, Map.class);
//
//		log.info("\n\n\n\nloginByToken response \n{}\n\n\n\n", jsonstr);
//
//		if (!jsonMap.get("code").toString().equals("200")) {
//			response.setSuccess(false);
//			response.setMessage("token 验证失败" + jsonMap.get("msg").toString());
//			return response;
//		}
//
//		log.info("token 解析:" + jsonstr);
//
//		// 服务之窗返回 结果 转 bean
//		TokenUserBySuperdeskApp tokenUserByService = JSONObject.parseObject(jsonMap.get("data").toString(), TokenUserBySuperdeskApp.class);
        /****************************************** 重构 mark by linjinyu at 20210615 start ******************************************/


        SupperdeskAppResponse<SupperdeskAppTokenUser> supperdeskAppResponse = AnJsonUtils.getMapper().readValue(responseJsonStr, new TypeReference<SupperdeskAppResponse<SupperdeskAppTokenUser>>() {
        });

        log.info("\n返回\n{}\n转换\n{}\n", responseJsonStr, AnJsonUtils.toJson(supperdeskAppResponse));

        if (null == supperdeskAppResponse.getCode() || !supperdeskAppResponse.getCode().equals(200)) {
            response.setSuccess(false);
            response.setMessage("token 验证失败" + responseJsonStr);
            return response;
        }

        SupperdeskAppTokenUser supperdeskAppTokenUser = supperdeskAppResponse.getData();

        SysUserVo responseVo = sysUserDubboConsumerService.userLoginBySupperDeskUniServiceTokenFacade(supperdeskAppTokenUser);

        if (null == responseVo) {
            response.setSuccess(false);
            response.setMessage("您还未开通运营商项目和业务权限,请联系管理员配置");
            return response;
        }

        if (supperdeskAppTokenUser.getTokenType() == null) {
            response.setSuccess(false);
            response.setMessage("tokenType 不能为 null");
            return response;
        }

        if (supperdeskAppTokenUser.getTokenType().equals(2) && responseVo.getSysRoleExtDataId() == null) {
            response.setSuccess(false);
            response.setMessage("您没有权限,或系统中无关联【数据权限】角色。请联系管理员！");
            return response;
        }

        if (supperdeskAppTokenUser.getTokenType().equals(2) && responseVo.getRoleId() == null) {
            response.setSuccess(false);
            response.setMessage("您没有权限,或系统中无关联【菜单权限】角色。请联系管理员！");
            return response;
        }

        responseVo.setTokenUserByService(supperdeskAppTokenUser);
        response.setData(responseVo);

        return response;

    }

    @ApiOperation(value = "系统(后台)用户列表-分页")
    @PostMapping("/findAllByPage")
    @ResponseBody
    public R<List<SysUserView>> findAllByPage(@RequestBody SysUserQueryCriteria queryCriteria) {

        R<List<SysUserView>> result = new R<>();

        /**************************************** 默认 start ****************************************/

        if (ObjectUtil.isNull(queryCriteria.getEnabled())) {
            queryCriteria.setEnabled(CommonEnabledEnum.启用.getKey());
        }

        if (ObjectUtil.isNull(queryCriteria.getDeleted())) {
            queryCriteria.setDeleted(CommonSoftDeleteEnum.正常.getKey());
        }

        String[] sourceFromContains = {
                CommonSourceFromEnum.结算中心.getSourceFromCode()
        };

        if (CollUtil.isEmpty(queryCriteria.getSourceFromsSelected())) {
            queryCriteria.setSourceFromsSelected(Arrays.asList(sourceFromContains));
        }


        /**************************************** 默认   end ****************************************/

        try {


            result = sysUserDubboConsumerService.findAllPage(queryCriteria);

        } catch (Exception e) {

            result.setCode(String.valueOf(e.hashCode()));
            result.setSuccess(false);
            result.setMessage("系统查找失败！");

            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
        }

        return result;
    }

    @PostMapping("/refreshToken")
    @ResponseBody
    public R<SysUserVo> refreshToken(String refreshToken) throws ServletException {

        R<SysUserVo> result = new R<SysUserVo>();

//		if (StringUtils.isEmpty(refreshToken)) {
//			result.setSuccess(false);
//			result.setMessage("refreshToken为空。");
//			return result;
//		}
//
//		String userId = JwtUtil.checkToken(refreshToken);
//
//		if (StringUtils.isEmpty(userId)) {
//			result.setSuccess(false);
//			result.setMessage("token expired");
//		} else {
//			Object objRefreshToken = redisService.hgetKey(RedisKeyPrefix.TOKEN_CACHE.getKey() + ":" + userId,
//					"refreshToken");
//
//			if (objRefreshToken == null || !refreshToken.equals(objRefreshToken.toString())) {
//				result.setSuccess(false);
//				result.setMessage("token expired");
//			} else {
//				// refresh token
//				SysUserVO user = service.refreshToken(userId);
//				result.setData(user);
//			}
//		}

        return result;
    }

    /**
     * 系統管理 > 用户管理 > op添加
     * 新增或修改接口
     *
     * @param model
     * @return
     */
    @PostMapping("/saveOrUpdate")
    @ResponseBody
    public R<?> saveOrUpdate(SysUserModify model) {

        R<?> result = new R<>();

        try {
            // 为了不用改
            List<SysUserOrderSourcetypeKey> sysUserOrderSourcetypeKeys = new ArrayList<SysUserOrderSourcetypeKey>();

//			if (!StringUtils.isEmpty(model.getSourcetypes())) {
//
//				String[] types = model.getSourcetypes().split(",");
//
//				for (int i = 0; i < types.length; i++) {
//					SysUserOrderSourcetypeKey key = new SysUserOrderSourcetypeKey();
//					key.setSourcetypeId(Long.valueOf(types[i]));
//					ls.add(key);
//				}
//			}

            SysUser sysUser = AnConvertBeanUtil.copyBean(model, SysUser.class);

            if (StrUtil.isBlank(sysUser.getSourceFrom())) {
                sysUser.setSourceFrom(CommonSourceFromEnum.结算中心.getSourceFromCode());
            }

            if (model.getId() == null) {
                // 新增
                sysUserDubboConsumerService.add(sysUser, sysUserOrderSourcetypeKeys, getToken());
                result.setSuccess(true);

            } else {
                // 修改
                sysUserDubboConsumerService.edit(sysUser, sysUserOrderSourcetypeKeys, getToken());
                result.setSuccess(true);
            }

        } catch (Exception e) {

            result.setSuccess(false);
            result.setMessage("用户名已经存在！");
            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
        }

        return result;
    }

    @Deprecated
    @ApiModelProperty(value = "物理删除 改 逻辑删除 软删除 物理删除-弃用")
    @PostMapping("/delete")
    public R<String> delete() {

//        return ResponseResultOuterUtils.createErrorResult("500", "弃用!请使用新接口");

        try {

            Long sysUserId = getLong("id");

            int ret = sysUserDubboConsumerService.opLogicalDelete(sysUserId, getToken());
            if (ret > 0) {
                return ResponseResultOuterUtils.createSuccesResult();
            } else {
                return ResponseResultOuterUtils.createErrorResult("500", "操作失败");
            }
        } catch (Exception e) {

            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
            return ResponseResultOuterUtils.createErrorResult("500", StrUtil.format("{}:{}", e.hashCode(), e.getMessage()));
        }

    }

    @ApiOperation(value = "物理删除-系统管理-用户管理", notes = "积分结算2.1")
    @PostMapping("/opPhysicsDelete/{sysUserId}")
    @ResponseBody
    public R<String> opPhysicsDelete(@PathVariable Long sysUserId) {

        try {
            int ret = sysUserDubboConsumerService.opPhysicsDelete(sysUserId, getToken());
            if (ret > 0) {
                return ResponseResultOuterUtils.createSuccesResult();
            } else {
                return ResponseResultOuterUtils.createErrorResult("500", "操作失败");
            }

        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
            return ResponseResultOuterUtils.createErrorResult("500", StrUtil.format("{}:{}", e.hashCode(), e.getMessage()));
        }
    }

    @ApiOperation(value = "逻辑删除-系统管理-用户管理", notes = "积分结算2.1")
    @PostMapping("/opLogicalDelete/{sysUserId}")
    @ResponseBody
    public R<String> opLogicalDelete(@PathVariable Long sysUserId) {

        try {

            int ret = sysUserDubboConsumerService.opLogicalDelete(sysUserId, getToken());
            if (ret > 0) {
                return ResponseResultOuterUtils.createSuccesResult();
            } else {
                return ResponseResultOuterUtils.createErrorResult("500", "操作失败");
            }

        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
            return ResponseResultOuterUtils.createErrorResult("500", StrUtil.format("{}:{}", e.hashCode(), e.getMessage()));
        }

    }


//	@PostMapping("/loginByToken")
//	@ResponseBody
//	public ResponseResult<SysUserVO> loginByToken(String token) throws MyException {
//
//		return new ResponseResult<>(service.loginByToken(token));
//	}

//	@PostMapping("/listSysUser")
//	public ResponseResult<List<SysUserQueryVO>> listSysUser(@RequestBody SysUserParamsVO vo) throws MyException {
//		return service.listSysUser(vo);
//	}
//
//	@PostMapping("/getSysUser")
//	public ResponseResult<SysUserEditVO> getSysUser(@RequestBody SysUserParamsVO vo) throws MyException {
//		return service.getSysUser(vo);
//	}

    /***
     * 检查用户电话是否存在
     *
     * @return
     */
    @RequestMapping("/ckUserExist")
    @ResponseBody
    public R<SysUser> checkUserExistByContactNumber(String contactNumber) {

        R<SysUser> result = new R<>();

//		try {
//			SysUser user = service.findByContact(contactNumber);
//			if (user != null) {
//				result.setData(user);
//				result.setMessage("用户联系电话已存在,请重新输入！");
//				result.setSuccess(false);
//			} else {
//				result.setSuccess(true);
//			}
//
//		} catch (Exception e) {
//
//			result.setMessage("获取数据失败！");
//			result.setSuccess(false);
//		}

        return result;

    }

    /**
     * 返回平台方公司信息-目前写死
     *
     * @return
     */
    @PostMapping("/getSysCompany")
    @ResponseBody
    public R<SysCompany> getSysCompany() {

        R<SysCompany> result = new R<>();

        try {

            SysCompany company = sysUserDubboConsumerService.getSysCompany(1L);

            result.setSuccess(true);
            result.setData(company);

        } catch (Exception e) {

            result.setCode(String.valueOf(e.hashCode()));
            result.setSuccess(false);
            result.setMessage("系统查找失败！");

            log.error(ExceptionUtils.getMessage(e));
            e.printStackTrace();
        }
        return result;
    }


    private static final String CODE_RANGE = "23456789ABDEFHJKLMNPQRSTUVWXYZ";

    /**
     * 生成验证码
     *
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/imageCode", method = RequestMethod.POST)
    public String imageCode(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
        // 在内存中创建图象
        int           width = 65, height = 20;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取图形上下文
        Graphics g = image.getGraphics();
        // 生成随机类
        Random random = new Random();
        // 设定背景色
        g.setColor(getRandColor(230, 255));
        g.fillRect(0, 0, 100, 25);
        // 设定字体
        g.setFont(new Font("Arial", Font.CENTER_BASELINE | Font.ITALIC, 18));
        // 产生0条干扰线,
        g.drawLine(0, 0, 0, 0);
        // 取随机产生的认证码(4位数字)
        String sRand = "";
        for (int i = 0; i < 4; i++) {
            String rand = CODE_RANGE.charAt((int) (Math.random() * CODE_RANGE.length())) + "";
            sRand += rand;
            // 将认证码显示到图象中
            g.setColor(getRandColor(100, 150));// 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
            g.drawString(rand, 15 * i + 6, 16);
        }
        for (int i = 0; i < (random.nextInt(5) + 5); i++) {
            g.setColor(new Color(random.nextInt(255) + 1, random.nextInt(255) + 1, random.nextInt(255) + 1));
            g.drawLine(random.nextInt(100), random.nextInt(30), random.nextInt(100), random.nextInt(30));
        }
        //String superId = request.getParameter("super");
        //String key = superId + "_checkCode";
        // 将验证码存入页面KEY值的SESSION里面
        session.setAttribute("verificationCode", sRand);

        log.info("\nimageCode\nsessionId:{}\nsessionVerificationCode:{}", session.getId(), session.getAttribute("verificationCode"));

//		log.info("session.setAttribute: verificationCode = {}", sRand);

        //session.setAttribute("keys", sRand);
        // 图象生效
        g.dispose();
        ServletOutputStream responseOutputStream = response.getOutputStream();
        // 输出图象到页面
        ImageIO.write(image, "JPEG", responseOutputStream);
        // 以下关闭输入流！
        responseOutputStream.flush();
        responseOutputStream.close();
        // 获得页面key值
        return null;
    }

    /**
     * 给定范围获得随机颜色
     *
     * @param fc
     * @param bc
     * @return
     */
    Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255)
            fc = 255;
        if (bc > 255)
            bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }
}
