package com.dcsoft.system.visitor.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dcsoft.common.core.constant.CacheConstants;
import com.dcsoft.common.core.constant.Constants;
import com.dcsoft.common.core.domain.R;
import com.dcsoft.common.core.enums.exception.CommonExceptionEnum;
import com.dcsoft.common.core.exception.ServiceException;
import com.dcsoft.common.core.web.controller.BaseController;
import com.dcsoft.common.core.web.domain.AjaxResult;
import com.dcsoft.common.core.web.page.TableDataInfo;
import com.dcsoft.common.core.web.page.TableDataInfoPage;
import com.dcsoft.common.redis.service.RedisService;
import com.dcsoft.system.api.RemoteFileService;
import com.dcsoft.system.api.domain.SysFile;
import com.dcsoft.system.domain.*;
import com.dcsoft.system.service.*;
import com.dcsoft.system.uniubi.domain.DingtalkMsgVo;
import com.dcsoft.system.utils.PictureUtils;
import com.dcsoft.system.visitor.domain.*;
import com.dcsoft.system.visitor.service.IVisitorService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/visitorMachine")
public class VisitorMachineController extends BaseController {

    @Autowired
    private IVisitorService visitorService;

    @Autowired
    private RemoteFileService remoteFileService;

    @Autowired
    protected ISysEquipmentService equipmentService;

    @Autowired
    private ISysEmpowerRecordService sysEmpowerRecordService;

    @Autowired
    private ISysBranchService sysBranchService;

    @Autowired
    private ISysBlackListService sysBlackListService;

    @Autowired
    private RemoteFileService fileService;

    @Autowired
    private ISysPeopleService sysPeopleService;

    @Autowired
    private RedisService redisService;

    @Value("${system.type}")
    public String systemType;

    @Value("${sdk.saveVisitorMachine}")
    public String saveVisitorMachine;

    @Value("${sdk.updateState}")
    public String updateState;

    @Value("${sdk.updateGroupSignOut}")
    public String updateGroupSignOut;

    @Value("${sdk.updateParkSignOut}")
    public String updateParkSignOut;

    @Value("${dingTalk.agentId}")
    public String agentId;

    @Value("${dingTalk.asyncsendV2}")
    public String asyncsendV2;

    @Value("${dingTalk.getToken}")
    public String getToken;

    @Value("${weCom.token}")
    public String qywxToken;

    @Value("${weCom.send}")
    public String qywxSend;

    @Value("${weCom.agentid}")
    public String agentid;

    /**
     * 访客机新增
     */
    @PostMapping("/saveVisitorMachine")
    public AjaxResult saveVisitorMachine(@RequestBody Visitor visitor) throws ParseException {

        log.info("访客机新增参数：" + visitor);
        // 判断是否是黑名单
        SysBlackList sysBlackList = sysBlackListService.queryBlackById(visitor);
        if(sysBlackList != null) {
            throw new ServiceException("您已拉入黑名单");
        }
        if(visitor.getStartTime().getTime() > visitor.getEndTime().getTime()) {
            throw new ServiceException("您输入的开始时间不能大于结束时间");
        }

        // todo 身份证信息获取后推送服务器进行公安比对
        if(StringUtils.isEmpty(visitor.getName())) {
            throw new ServiceException("姓名不能为空");
        }
        if(visitorService.queryVisitor(visitor) > 0) {
            throw new ServiceException("您已预约");
        }

        int i = 0;
        List<String> list = new ArrayList<>();
        Visitor visitor2 = new Visitor();
        BeanUtils.copyProperties(visitor, visitor2);
        visitor2.setCreateTime(visitor.getCreateTime());
        visitor2.setStartTime(visitor.getCreateTime());
        visitor2.setSource(Constants.ZERO);
        visitor2.setDeptId(2L);
        MultipartFile file = PictureUtils.base64ToMultipartFiles(visitor.getAvatar());
        R<SysFile> sysFileR = fileService.uploadMinio1(file, "true");
        visitor2.setAvatar(sysFileR.getData().getUrl());
        i = visitorService.insertVisitor(visitor2);
        List<Visitor> itemList=visitor.getItemList();
        visitor.setId(visitor2.getId());
        list.add(String.valueOf(visitor2.getId()));
        // 随访人员
        if(!CollectionUtils.isEmpty(itemList)) {
            for (Visitor item:itemList) {
                MultipartFile multipartFile = PictureUtils.base64ToMultipartFiles(visitor.getAvatar());
                R<SysFile> uploadMinio = fileService.uploadMinio1(multipartFile, "true");
                item.setAvatar(uploadMinio.getData().getUrl());
                item.setParentId(visitor2.getId());
                item.setSource(Constants.ZERO);
                item.setUserId(item.getUserId());
                item.setDeptId(item.getDeptId());
                item.setCreateTime(new Date());
                item.setStartTime(visitor2.getStartTime());
                item.setEndTime(visitor2.getEndTime());
                item.setSource(Constants.ZERO);
                visitorService.insertVisitor(item);
            }
        }

        SysPeople sysPeople = sysPeopleService.selectSysPeopleByUserId(visitor.getUserId());
        // 钉工牌消息通知
        if(sysPeople != null && StringUtils.isNotEmpty(sysPeople.getQwid())) {
            // 数据同步到子园区
            ThreadUtil.execAsync(() -> {
                try {
                    String url = "您有新的访客申请，请审核: https://thzn.chinataiho.com/h5/#/pages/visitor/visitor/examineDetal?id="+ visitor2.getId();
                    //asyncsendV2(sysPeople.getGh(), "text", url);
                    String wxToken = getQyWxToken();
                    qywxSend(sysPeople.getQwid(), wxToken, url);
                } catch (HttpException e) {
                    log.error("钉钉通知失败", e);
                    throw new RuntimeException(e);
                }
            });

        }
        /*if("2".equals(systemType)) {
            // 数据同步到子园区
            ThreadUtil.execAsync(() -> {
                try {
                    String body = HttpUtil.createPost(saveVisitorMachine).body(JSON.toJSONString(visitor)).execute().body();
                    log.info("数据同步到总部结果：{}", body);
                } catch (HttpException e) {
                    log.error("数据同步到总部失败", e);
                    throw new RuntimeException(e);
                }
            });
        }*/
        return toAjax(i);
    }

    /**
     * 获取微信公众号token
     *
     * @return
     */
    private String getQyWxToken() {
        String cacheObject = redisService.getCacheObject(CacheConstants.QYWEIXIN_TOKEN);
        if (StringUtils.isNotEmpty(cacheObject)) {
            return cacheObject;
        }
        String body = HttpUtil.createGet(qywxToken).execute().body();
        JSONObject object = JSONObject.parseObject(body);
        String string = object.get("access_token").toString();
        redisService.setCacheObject(CacheConstants.QY_LOGIN_TOKEN, string, Long.valueOf(object.get("expires_in").toString()), TimeUnit.SECONDS);
        return string;
    }

    private void qywxSend(String gh, String wxToken, String content) {

        Map<String, Object> paramMap=new HashMap<>();
        Map<String, Object> paramMap1=new HashMap<>();
        paramMap.put("touser",gh);
        paramMap.put("msgtype","text");
        paramMap.put("agentid",agentid);
        paramMap1.put("content",content);
        paramMap.put("text",paramMap1);
        String body1=JSON.toJSONString(paramMap);
        String body=HttpUtil.post(qywxSend+wxToken,body1);
        JSONObject object = JSONObject.parseObject(body);
        if (!"0".equals(object.get("errcode").toString())) {
            throw new ServiceException(CommonExceptionEnum.REQUEST_ERROR.getCode(), "企业微信消息通知接口" + CommonExceptionEnum.REQUEST_ERROR.getMessage() + object.get("errcode").toString());
        }

    }

    /**
     * 钉工牌消息通知
     */
    private void asyncsendV2(String userId, String msgType, String content) {
        DingtalkMsgVo msgVo = new DingtalkMsgVo();
        DingtalkMsgVo.Text text = new DingtalkMsgVo.Text();
        text.setContent(content);
        msgVo.setMsgtype(msgType);
        msgVo.setText(text);
        Map<String, Object> map = new HashMap<>();
        map.put("agent_id", agentId);
        map.put("msg", msgVo);
        map.put("userid_list", userId);
        String body = HttpUtil.createPost(asyncsendV2 + "?access_token=" + getToken())
                .body(JSON.toJSONString(map))
                .execute()
                .body();
        JSONObject object = JSONObject.parseObject(body);
        if(!Constants.ZERO.equals(object.get("errcode").toString())) {
            log.error("钉工牌消息通知接口异常码:" + object.get("errcode").toString());
            throw new ServiceException(CommonExceptionEnum.REQUEST_ERROR.getCode(), "钉工牌消息通知接口" + CommonExceptionEnum.REQUEST_ERROR.getMessage());
        }

    }

    /**
     * 获取钉工牌token
     */
    private String getToken() {
        String body = HttpUtil.createGet(getToken).execute().body();
        JSONObject object = JSONObject.parseObject(body);
        return object.get("access_token").toString();

    }

    /**
     * 获取时间
     * @param startDate
     * @param endDate
     */
    private List<Visitor> getTime(String startDate, String endDate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        LocalDate start = LocalDate.parse(startDate);
        LocalDate end = LocalDate.parse(endDate);
        List<Visitor> list = new ArrayList<>();
        while (!start.isAfter(end)) {
            Visitor gather = new Visitor();
            gather.setCreateTime(sdf.parse(start.toString()));
            list.add(gather);
            start = start.plusDays(1);
        }
        return list;
    }

    /**
     * 查询访客预约信息
     */
    @PostMapping("/queryVisitorAppointment")
    public TableDataInfoPage queryVisitorAppointment(@RequestBody VisitorParamVo paramVo) {
        log.info("查询访客预约信息(入参)：" + paramVo);
        TableDataInfoPage tableDataInfoPage = visitorService.queryVisitorAppointment(paramVo);
        log.info("查询访客预约信息(出参)：" + tableDataInfoPage);
        return tableDataInfoPage;
    }

    /**
     * 查询黑名单
     */
    @PostMapping("/selectSysBlackListList")
    public TableDataInfoPage selectSysBlackListList(@RequestBody VisitorParamVo paramVo) {
        log.info("查询黑名单（入参）：" + paramVo);
        TableDataInfoPage tableDataInfoPage = visitorService.selectSysBlackListList(paramVo);
        log.info("查询黑名单(出参)：" + tableDataInfoPage);
        return tableDataInfoPage;
    }

    /**
     * 二维码校验
     */
    @PostMapping("/checkQrCode")
    public AjaxResult checkQrCode(@RequestBody EwmInfoVo info) {
        log.info("二维码校验（入参）：" + info);
        System.out.println("======二维码回调信息============="+info);
        CheckCodeVo codeVo = visitorService.queryVisCheckCodeById(info.getQrData());
        if(!codeVo.getCode().contains("/pages/visitor/visitor/visExamineEwm")) {
            throw new ServiceException("无效验证码");
        }
        String[] ids = codeVo.getCode().split("id=");
        String[] split = ids[1].split("&time=");
        Visitor visitor = visitorService.selectVisitorById(Long.valueOf(split[0]));
        if(visitor == null) {
            return success(new Visitor());
        }
        if(visitor.getEndTime().getTime() < Long.parseLong(info.getTime())) {
            throw new ServiceException("您得验证码已超时");
        }

        log.info("二维码校验(出参)：" + visitor);
        return success(visitor);
    }

    /**
     * 修改访客信息
     */
    @PostMapping("/updateVisitor")
    public AjaxResult updateVisitor(@RequestBody Visitor paramVo) {
        log.info("修改访客信息：" + paramVo);
        if(paramVo.getStartTime().getTime() > paramVo.getEndTime().getTime()) {
            throw new ServiceException("您输入的开始时间不能大于结束时间");
        }
        visitorService.deleteVisitorItemByParentId(paramVo.getId());
        List<Visitor> itemList=paramVo.getItemList();
        if(!CollectionUtils.isEmpty(itemList)) {
            for(Visitor item:itemList){
                item.setParentId(paramVo.getId());
                item.setSource(Constants.ZERO);
                visitorService.insertVisitor(item);
            }
        }

        return toAjax(visitorService.updateVisitor(paramVo));
    }

    /**
     * 修改状态
     */
    @PostMapping("/updateState")
    public AjaxResult updateState(@RequestBody Visitor paramVo) {
        log.info("修改状态：" + paramVo);
        /*if("2".equals(systemType)) {
            // 数据同步到总部
            ThreadUtil.execAsync(() -> {
                try {
                    String body = HttpUtil.createPost(updateState).body(JSON.toJSONString(paramVo)).execute().body();
                    log.info("修改状态同步到总部结果：{}", body);
                } catch (HttpException e) {
                    log.error("修改状态同步到总部失败", e);
                    throw new RuntimeException(e);
                }
            });
        }*/
        int i = visitorService.updateState(paramVo);
        return toAjax(i);
    }

    /**
     * 修改状态
     */
    @PostMapping("/updateSignOut")
    public AjaxResult updateSignOut(@RequestBody Visitor paramVo) {
        log.info("修改状态签离：" + paramVo);
        // 同步园区签离
        /*if("1".equals(systemType)) {
            ThreadUtil.execAsync(() -> {
                try {
                    String body = HttpUtil.createPost(updateParkSignOut).body(JSON.toJSONString(paramVo)).execute().body();
                    log.info("同步园区签离结果：{}", body);
                } catch (HttpException e) {
                    log.error("同步园区签离失败", e);
                    throw new RuntimeException(e);
                }
            });
        }*/

       /* // 同步总部签离
        if("2".equals(systemType)) {
            ThreadUtil.execAsync(() -> {
                try {
                    String body = HttpUtil.createPost(updateGroupSignOut).body(JSON.toJSONString(paramVo)).execute().body();
                    log.info("同步总部签离结果：{}", body);
                } catch (HttpException e) {
                    log.error("同步总部签离失败", e);
                    throw new RuntimeException(e);
                }
            });
        }*/
        return toAjax(visitorService.updateSignOut(paramVo));
    }

    /**
     * 查询被访人
     */
    @PostMapping("/queryPeople")
    public AjaxResult queryPeople(Visitor paramVo) {
        log.info("查询被访人(入参)：" + paramVo);
        List<PersonnelInfoVo> infoVos = visitorService.queryPeople(paramVo);
        if(!CollectionUtils.isEmpty(infoVos)) {
            for (PersonnelInfoVo infoVo : infoVos) {
                if(StringUtils.isNotEmpty(infoVo.getPhone())) {
                    infoVo.setPhone(infoVo.getPhone().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
                }
            }
        }

        log.info("查询被访人(出参)：" + infoVos);
        return success(infoVos);
    }

    /**
     * 查询已审核状态信息
     */
    @PostMapping("/queryAuditedVisitor")
    public AjaxResult queryAuditedVisitor(@RequestBody Visitor paramVo) {
        log.info("查询已审核状态信息：" + paramVo);
        return success(visitorService.queryAuditedVisitor(paramVo));
    }

    /**
     * 查询详情
     */
    @PostMapping("/queryVisitorInfo")
    public AjaxResult queryVisitorInfo(@RequestBody Visitor paramVo) {
        log.info("查询详情(入参)：" + paramVo);
        VisitorInfoVo visitorInfoVo = visitorService.queryVisitorInfo(paramVo);
        log.info("查询详情（出参）：" + visitorInfoVo);
        return success(visitorInfoVo);
    }

    /**
     * 查询部门
     */
    @PostMapping("/queryDeptInfo")
    public AjaxResult queryDeptInfo(@RequestBody SysBranch paramVo) {
        log.info("查询部门：" + paramVo);
        return success(sysBranchService.queryDeptInfo(paramVo));
    }

    /**
     * 查询未签离列表
     */
    @GetMapping("/queryVisitorUnsigned")
    public TableDataInfo queryVisitorUnsigned(VisitorParamVo paramVo) {
        log.info("查询未签离列表(入参)：" + paramVo);
        List<Visitor> list = visitorService.queryVisitorUnsigned(paramVo);
        log.info("查询未签离列表(出参)：" + list);
        return getDataTable(list);
    }


    /**
     * 查询访客二维码 码值
     * @param visitorId
     * @return
     */
    @PostMapping("/queryVisCheckCode")
    public AjaxResult queryVisCheckCode(String visitorId) {
        log.info("访客id（参数）：" + visitorId);
        return success(visitorService.queryVisCheckCode(visitorId));
    }
}
