package com.yizhi.application.wechat.controller;

import com.alibaba.fastjson.JSON;
import com.yizhi.application.wechat.utils.WechatInfoService;
import com.yizhi.calendar.application.feign.CalendarClient;
import com.yizhi.calendar.application.vo.CalendarVO;
import com.yizhi.core.application.cache.RedisCache;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.token.TokenHelper;
import com.yizhi.site.application.enums.FunctionTypeCode;
import com.yizhi.site.application.feign.api.FunctionDisplayConfigApiClients;
import com.yizhi.site.application.feign.api.MyItemConfigApiClients;
import com.yizhi.site.application.feign.api.MyItemConfigDefaultApiClients;
import com.yizhi.site.application.vo.domain.FunctionDisplayConfigVo;
import com.yizhi.site.application.vo.site.MyItemConfigVO;
import com.yizhi.system.application.system.remote.AccountClient;
import com.yizhi.system.application.system.remote.LoginLogClient;
import com.yizhi.system.application.system.remote.SiteClient;
import com.yizhi.system.application.vo.AccountVO;
import com.yizhi.system.application.vo.LoginLogAddReqVO;
import com.yizhi.util.application.constant.GlobalConstant;
import com.yizhi.util.application.constant.ReturnCode;
import com.yizhi.util.application.domain.Response;
import com.yizhi.wechat.application.feign.MiniProgramClient;
import com.yizhi.wechat.application.vo.wechat.Constants;
import com.yizhi.wechat.application.vo.wechat.MiniProgramVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 小程序接口
 *
 * @author lilingye
 * @since 2020-1-3
 */
@RestController
@Api(tags = "小程序获取token接口")
@RequestMapping("/public/miniProgram")
public class MiniProgramController {

    private static final Logger LOGGER = LoggerFactory.getLogger(MiniProgramController.class);
    @Autowired
    private MiniProgramClient miniProgramClient;
    @Autowired
    private TokenHelper tokenHelper;
    @Autowired
    private AccountClient accountClient;
    @Autowired
    private SiteClient siteClient;
    @Autowired
    LoginLogClient loginLogClient;
    @Autowired
    WechatInfoService wechatInfoService;
    @Autowired
    FunctionDisplayConfigApiClients functionClient;
    @Autowired
    private MyItemConfigApiClients myItemConfigApiClients;
    @Autowired
    private MyItemConfigDefaultApiClients myItemConfigDefaultApiClients;
    @Autowired
    private CalendarClient calendarClient;
    @Autowired
    private RedisCache redisCache;

    @ApiOperation(value = "小程序用户接口", notes = "查询用户是否")
    @GetMapping(value = "/get")
    public Response<String> queryUser(HttpServletResponse httpResponse,
                                      @ApiParam(name = "code", value = "code", required = true) @RequestParam(name = "code", required = true) String code,
                                      @ApiParam(name = "appId", value = "小程序appId", required = true) @RequestParam(name = "appId",required = true) String appId,
                                      @ApiParam(name = "headImg", value = "用户头像", required = false) @RequestParam(name = "headImg",required = false) String headImg
    ) {

        RequestContext context = ContextHolder.get();
        LOGGER.info("上下文信息：{}", JSON.toJSON(context));

        Map<String, Object> retMap = new HashMap<String, Object>(16);
        Long companyId = context.getCompanyId();
        Long siteId = context.getSiteId();
        MiniProgramVo miniProgram = null;

        try {
            //获取用户绑定信息
            miniProgram = miniProgramClient.getMiniProgram(appId, code, headImg);
            if (!Constants.ZERO.equals(miniProgram.getCode())) {
                return Response.fail(miniProgram.getCode(), miniProgram.getMsg());
            }
        } catch (Exception e) {
            LOGGER.info("wechat服务异常：{}", e.getMessage());
            return Response.fail("微信服务异常");
        }

        //判断条件
        if (miniProgram.getRet()) {
            // 判断该用户是是否有 站点的访问权限
            if (getSiteAuthorize(miniProgram.getAccountId(), siteId, companyId)) {
                //如果用户存在微服务系统中
                AccountVO accountVO = accountClient.findById(miniProgram.getAccountId());
                context.setAccountId(miniProgram.getAccountId());
                //生成token
                String token = generateToken(context.getCompanyCode(), companyId, context.getCompanyName(), accountVO, siteId);
                // 签到打卡是否可见
                retMap.putAll(getEnableSign(siteId, accountVO.getId()));
                // 统计登录调用接口
                addUserLoginLog(companyId, siteId, accountVO);
                httpResponse.addHeader(GlobalConstant.TOKEN_HEADER, token);
                retMap.put(GlobalConstant.TOKEN_HEADER, token);
                retMap.put("userInfo", accountVO);
                ContextHolder.set(context);
                //返回用户信息和token
                return Response.ok(retMap);
            } else {
                return Response.fail(ReturnCode.NOT_SITE_AUTH.getCode(),ReturnCode.NOT_SITE_AUTH.getMsg());
            }
        } else {
            return Response.fail("4013", "您当前的微信号未关联系统账号,请先登录", miniProgram);
        }
    }

    /**
     * 判断站点是否有权
     *
     * @param siteId
     * @return
     */
    public Boolean getSiteAuthorize(Long accountId, Long siteId, Long companyId) {
        try {
            return siteClient.isAccessToSite(accountId, siteId, companyId);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 打卡方法
     *
     * @param siteId
     * @param accountId
     * @return
     */
    private Map<String, Object> getEnableSign(Long siteId, Long accountId) {
        Map<String, Object> map = new HashMap<>(16);
        try {
            return isEnableSign(siteId, accountId);
        } catch (Exception e) {
            map.put("isEnableSign", 0);
            LOGGER.error("服务异常", e);
            return map;
        }
    }

    /**
     * 签到打卡显示查询
     *
     * @param siteId
     * @param accountId
     * @return
     */
    public Map<String, Object> isEnableSign(Long siteId, Long accountId) {
        Map<String, Object> map = new HashMap<String, Object>(16);
        List<Integer> terminalType = new ArrayList<>();
        terminalType.add(2);
        terminalType.add(3);
        List<FunctionDisplayConfigVo> list = functionClient.getBySiteId(siteId);
        List<MyItemConfigVO> voList = myItemConfigApiClients.queryByAuthoity(terminalType);
        CalendarVO calendar = calendarClient.getCalendar();
        map.put("isEnableSign", 0);
        map.put("isPCEnableSign", 0);
        map.put("isAPPEnableSign", 0);
        if (calendar != null) {
            map.put("isEnableSign", calendar.getState());
            if (calendar.getState() == 1) {
                SimpleDateFormat format = new SimpleDateFormat("yyyMMdd");
                Date date = new Date();
                if (redisCache.exists(format.format(date) + accountId + siteId)) {
                    map.put("isFirstLogin", 0);
                } else {
                    redisCache.hset(format.format(date) + accountId + siteId, format.format(date) + accountId + siteId, "0", 86500L);
                    map.put("isFirstLogin", 1);
                }
            }
        } else {
            map.put("isFirstLogin", 0);
        }
        //如果我的配置表没有数据，取默认表里的数据
        if (CollectionUtils.isEmpty(voList)) {
            voList = myItemConfigDefaultApiClients.queryByAuthoity(terminalType);
        }
        if (!CollectionUtils.isEmpty(list)) {
            LOGGER.info("签到打卡PC端显示配置" + list.toString());
            for (FunctionDisplayConfigVo config : list) {
                if (config.getFunctionType().equals(FunctionTypeCode.SIGN.getCode()) && config.getShowDisplay()) {
                    map.put("isPCEnableSign", 1);
                }
            }
        }
        if (!CollectionUtils.isEmpty(voList)) {
            LOGGER.info("签到打卡移动端显示配置" + voList.toString());
            for (MyItemConfigVO vo : voList) {
                if (vo.getItemType() == 15 && vo.getShowable() == 1) {
                    map.put("isAPPEnableSign", 1);
                }
            }
        }
        return map;
    }


    /**
     * 用户登录统计
     *
     * @param companyId 公司id
     * @param siteId    站点id
     */
    public void addUserLoginLog(Long companyId, Long siteId, AccountVO accountVO) {
        LoginLogAddReqVO loginLogAddReqVO = new LoginLogAddReqVO();
        loginLogAddReqVO.setCompanyId(companyId);
        loginLogAddReqVO.setSiteId(siteId);
        // 小程序登录的记录
        loginLogAddReqVO.setType(4);
        loginLogAddReqVO.setAccountId(accountVO.getId());
        loginLogAddReqVO.setOrgId(accountVO.getOrgId());

        try {
            loginLogClient.addLoginLog(loginLogAddReqVO);
        } catch (Exception e) {
            LOGGER.error("统计用户异常：{}", e.getMessage());
        }
    }

    /**
     * 生成token
     *
     * @param companyCode 公司信息
     * @param accountVO   用户信息
     * @param siteId      站点id
     * @return 字符串的token
     */
    public String generateToken(String companyCode, Long companyId, String companyName, AccountVO accountVO, Long siteId) {

        Map<String, Object> info = new HashMap<String, Object>(16);
        info.put(GlobalConstant.ACCOUNT_ID, accountVO.getId().toString());
        info.put(GlobalConstant.COMPANY_CODE, companyCode);
        info.put(GlobalConstant.COMPANY_ID, companyId.toString());
        info.put(GlobalConstant.COMPANY_NAME, companyName);
        info.put(GlobalConstant.SITE_ID, siteId.toString());
        return tokenHelper.createToken(accountVO.getName(), info);
    }
}
