package com.template.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.seewo.open.sdk.DefaultSeewoClient;
import com.seewo.open.sdk.SeewoClient;
import com.seewo.open.sdk.auth.Account;
import com.template.api.SmartVisitorControllerAPI;
import com.template.common.utils.CommonUtil;
import com.template.common.utils.RequestUtils;
import com.template.common.utils.TimeExchange;
import com.template.common.utils.paramUtils;
import com.template.config.ParkConfig;
import com.template.config.SeewoConfig;
import com.template.model.enumModel.*;
import com.template.model.pojo.*;
import com.template.model.request.otherAppointmentRequest;
import com.template.model.request.parentsAppointmentRequest;
import com.template.model.request.turnOnTheDeviceRequest;
import com.template.model.result.CommonResult;
import com.template.model.result.PageUtils;
import com.template.model.seewo.HomeSchoolServiceSendNoteToKidParam;
import com.template.model.seewo.HomeSchoolServiceSendNoteToKidRequest;
import com.template.model.seewo.HomeSchoolServiceSendNoteToKidResult;
import com.template.model.vo.*;
import com.template.services.SmartAuthorGroupService;
import com.template.services.SmartQrcodeService;
import com.template.services.SmartUserService;
import com.template.services.SmartVisitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

import static com.template.common.utils.AesTestOne.decrypt;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author ceshi
 * @since 2023-12-04
 */
@RestController
public class SmartVisitorController implements SmartVisitorControllerAPI {

    @Autowired
    private SmartAuthorGroupService smartAuthorGroupService;

    @Autowired
    private SmartVisitorService smartVisitorService;

    @Autowired
    private SmartQrcodeService smartQrcodeService;

    @Autowired
    private SmartUserService smartUserService;

    @Resource
    private SeewoConfig seewoConfig;

    @Resource
    private ParkConfig parkConfig;

    /**
     * 新增访客预约
     *
     * @param smartApply    访客预约数据
     * @param bindingResult
     * @return
     */
    @Override
    public CommonResult insertSmartVisitor(SmartVisitor smartApply, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        int result = smartVisitorService.insertSmartVisitor(smartApply);

        return result > 0 ? CommonResult.ok("添加成功") : CommonResult.fail("添加失败");
    }

    /**
     * 更新访客预约
     *
     * @param sa            访客预约数据
     * @param bindingResult
     * @return
     */
    @Override
    public CommonResult updateSmartVisitorById(SmartVisitor sa, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        int result = smartVisitorService.updateSmartVisitor(sa);
        return result > 0 ? CommonResult.ok("修改成功") : CommonResult.fail("修改失败");
    }

    /**
     * 访客预约分页数据查询
     *
     * @param currentPage 当前页数
     * @param pageCount   一页数据条数
     * @param name        查询名称
     * @return
     */
    @Override
    public CommonResult queryPageSmartVisitor(int currentPage, int pageCount, String name) {
        PageUtils<SmartVisitor> result = smartVisitorService.queryPageSmartVisitors(currentPage, pageCount, name);

        return CommonResult.ok(result);
    }


    @Override
    public CommonResult deleteSmartVisitorById(int id) {

        SmartVisitor data = smartVisitorService.getSmartById(id);
        if (data == null) {
            return CommonResult.fail("当前数据不存在，删除失败！");
        }

        //审核通过就不能删除
        if(data.getStatu().intValue() == eApproveStatu.Pushed.getValue()){
            return CommonResult.fail("无法删除已审核通过的访客数据");
        }

        //已审核通过的数据不能删除 那么就不需要进行下面这些操作
        //region 推送到希沃班牌，通知访客记录取消
        //endregion
        //region 删除百胜中的访客数据
        //endregion

        int result = smartVisitorService.deleteSmartVisitorById(id);

        return result > 0 ? CommonResult.ok("删除成功") : CommonResult.fail("删除失败");
    }

    @Override
    public CommonResult parentsAppointment(parentsAppointmentRequest par, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        //参数判断 判断受访学生信息是否为空
        if (par.getStudents() == null) {
            return CommonResult.fail("请选择受访学生");
        }

        if (par.getStudents().size() <= 0) {
            return CommonResult.fail("请选择受访学生");
        }

        //根据用户ID查询相关信息
        SmartUser su = smartUserService.getSmartById(par.getUserId());
        if (su == null) {
            return CommonResult.fail("当前用户信息不合法，无法进行预约！");
        }

        String startTime = par.getVisitorTime();
        String endTime = TimeExchange.getEndOfDayStr(TimeExchange.StringToDate(startTime, "yyyy-MM-dd HH:mm:ss"));

        //要进行家长数据重复判断
        //那是不是第二次预约的时间不能在那个可访问的时间段内
        //例如：比如，第一次约了7：00-10：00；那第二次：6：00-7：30 或 8：11-13：00都不行
        Integer count = smartVisitorService.queryVisitorCount(su.getIdCard(), startTime, endTime);
        if (count > 0) {
            return CommonResult.fail("该时间段已预约，请勿重复预约！");
        }

        List<SmartVisitor> svs = new ArrayList<>();
        for (AffiliateUserVo student : par.getStudents()) {
            SmartVisitor sv = new SmartVisitor();
            sv.setUserId(par.getUserId());
            sv.setUserName(su.getName());
            sv.setUserPhone(su.getPhone());
            sv.setUserNumber(su.getIdCard());
            sv.setPeerNum(par.getPeerNum());
            //sv.setCarNum(par.getCarNum());家长预约不能填写车牌号
            sv.setVisitReason(par.getVisitReason());
            sv.setStatu(eApproveStatu.Audit.getValue());
            sv.setVisitorTime(TimeExchange.StringToDate(par.getVisitorTime(), "yyyy-MM-dd HH:mm:ss"));
            sv.setVisitorDeadline(TimeExchange.StringToDate(TimeExchange.TimeDesH(sv.getVisitorTime(), 4), "yyyy-MM-dd HH:mm:ss"));
            sv.setRespondent(student.getId());
            sv.setResponcode(student.getCardNo());
            sv.setRespondentName(student.getName());
            //将第一个受访学生的部门ID带过去
            sv.setDepartmentId(student.getDepartmentId());
            sv.setVisitorType(eVisitorType.Parent.getValue());
            svs.add(sv);
        }

        boolean result = smartVisitorService.insertVisitorBatch(svs);

        return result ? CommonResult.ok("预约成功，等待审批通过") : CommonResult.fail("预约失败");
    }

    @Override
    public CommonResult otherAppointment(otherAppointmentRequest oar, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        //根据用户ID查询相关信息
        SmartUser su = smartUserService.getSmartById(oar.getUserId());
        if (su == null) {
            return CommonResult.fail("当前用户信息不合法，无法进行预约！");
        }

        String startTime = oar.getVisitorTime();
        String endTime = TimeExchange.getEndOfDayStr(TimeExchange.StringToDate(startTime, "yyyy-MM-dd HH:mm:ss"));

        //要进行访客数据重复判断
        //那是不是第二次预约的时间不能在那个可访问的时间段内
        //例如：比如，第一次约了7：00-10：00；那第二次：6：00-7：30 或 8：11-13：00都不行
        Integer count = smartVisitorService.queryVisitorCount(su.getIdCard(), startTime, endTime);
        if (count > 0) {
            return CommonResult.fail("该时间段已预约，请勿重复预约！");
        }

        SmartVisitor sv = new SmartVisitor();
        sv.setUserId(oar.getUserId());
        sv.setUserName(su.getName());
        sv.setUserPhone(su.getPhone());
        sv.setUserNumber(su.getIdCard());
        sv.setPeerNum(oar.getPeerNum());
        sv.setCarNum(oar.getCarNum());
        sv.setVisitReason(oar.getVisitReason());
        sv.setStatu(eApproveStatu.Audit.getValue());
        sv.setVisitorTime(TimeExchange.StringToDate(startTime, "yyyy-MM-dd HH:mm:ss"));
        sv.setVisitorDeadline(TimeExchange.StringToDate(endTime, "yyyy-MM-dd HH:mm:ss"));
        sv.setRespondentName(oar.getRespondentName());
        sv.setRespondentPhone(oar.getRespondentPhone());
        sv.setVisitorType(eVisitorType.Other.getValue());

        int result = smartVisitorService.insertSmartVisitor(sv);

        return result > 0 ? CommonResult.ok("预约成功，等待审批通过") : CommonResult.ok("预约失败");
    }

    @Override
    public CommonResult appointmentPageRecord(int currentPage, int pageCount, Integer userId, int type, String createStartTime, String createEndTime, String keyWord, String visitorStartTime, String visitorEndTime) {
        PageUtils<VisitorPageVo> result = smartVisitorService.smartVisitorPageByUserId(currentPage, pageCount, userId, type, createStartTime, createEndTime, keyWord, visitorStartTime, visitorEndTime);

        return CommonResult.ok(result);
    }

    /**
     * 访客记录审核
     *
     * @param id   数据ID
     * @param type 操作类型：
     *             同意，并推送：1
     *             拒绝：2
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult examineRecord(int id, int type) throws Exception {
        SmartVisitor visitor = smartVisitorService.getSmartById(id);
        if (visitor == null) {
            return CommonResult.fail("访客记录已失效，审核失败！");
        }

        //审核处理后的数据不能再处理判断
        if(visitor.getStatu().intValue() != eApproveStatu.Audit.getValue()){
            return CommonResult.fail("该记录已被操作过，请勿重复操作");
        }

        try {
            if (type == eExamineStatu.Agree.getValue()) {
                visitor.setStatu(eApproveStatu.Pushed.getValue());

                //家长访客预约才需要将消息推送到希沃电子班牌
                if (visitor.getVisitorType().intValue() == eVisitorType.Parent.getValue()) {
                    String content = visitor.getRespondentName() + "你的家长将于" + TimeExchange.chineseDateTime(visitor.getVisitorTime()) + "到校！";
                    //将预约信息推送到希沃班牌
                    CommonResult seewo = pushInfo(visitor.getUserPhone(), visitor.getResponcode(), content);
                    if (!seewo.getCode().equals("200")) {
                        throw new Exception("审核失败");
                    }
                }
                //将数据写入门禁系统逻辑
                else {
                    //家长不能使用车牌系统 其他的可以使用车牌逻辑
                    if (!ObjectUtils.isEmpty(visitor.getCarNum())) {
                        String appId = parkConfig.getAppId();
                        String carNo = visitor.getCarNum();
                        String parkKey = parkConfig.getParkKey();
                        String rand = String.valueOf(Math.random());
                        String reserveTime = TimeExchange.DateToString(visitor.getVisitorTime(), "yyyy-MM-dd HH:mm:ss");
                        String reserveEndTime = TimeExchange.DateToString(visitor.getVisitorDeadline(), "yyyy-MM-dd HH:mm:ss");
                        String version = "v1.0";
                        String appSecret = parkConfig.getAppSecret();
                        String url = parkConfig.getUrl() + "Inform/Reservation";

                        JSONObject jsonobject = new JSONObject();
                        jsonobject.put("appid", appId);
                        jsonobject.put("carNo", carNo);
                        jsonobject.put("parkKey", parkKey);
                        jsonobject.put("rand", rand);
                        jsonobject.put("reserveEndTime", reserveEndTime);
                        jsonobject.put("reserveTime", reserveTime);
                        jsonobject.put("version", "v1.0");

                        //appid=ymdd36ed157ac423e2&carNo=赣U123659&parkKey=wdcmq9rc&rand=9.94995525689689966&reserveEndTime=2023-12-22 20:12:10&reserveTime=2023-12-21 18:12:10&version=v1.0&50596cd243dc4547b4c05f01f8ea02a4
                        String md5Str = "appid=" + appId + "&carNo=" + carNo + "&parkKey=" + parkKey + "&rand=" + rand + "&reserveEndTime=" + reserveEndTime + "&reserveTime=" + reserveTime + "&version=" + version + "&" + appSecret;
                        String sign = CommonUtil.MD5(md5Str);
                        //sign签名
                        jsonobject.put("sign", sign);

                        //返回的结果中 code为1表示成功
                        String result = RequestUtils.httpPost(url, jsonobject.toJSONString());

                        System.out.println(result);

                        if (!result.contains("预约成功")) {
                            throw new Exception("审核失败");
                        }

                        ObjectMapper objectMapper = new ObjectMapper();
                        BsReservationVo reservation = objectMapper.readValue(result, BsReservationVo.class);
                        visitor.setBsOrderNo(reservation.getData().getReOrderNo());
                    }
                }

            } else if (type == eExamineStatu.Refused.getValue()) {
                visitor.setStatu(eApproveStatu.Refused.getValue());
            }

            int result = smartVisitorService.updateSmartVisitor(visitor);
            if (result <= 0) {
                throw new Exception("审核失败");
            }

        } catch (Exception e) {
            throw new Exception("审核失败");
        }

        return CommonResult.ok("审核成功");
    }

    /**
     * 将预约信息推送到希沃电子班牌
     *
     * @param parentPhone 预约手机号（家长手机号 在希沃中学生会和家长手机号绑定 可以绑定多个家长）
     * @param studentCode 学生编号 希沃中的学生编号和万载系统中的一致
     * @param content     消息内容
     * @return
     */
    public CommonResult pushInfo(String parentPhone, String studentCode, String content) {
        //初始化客户端
        SeewoClient seewoClient = new DefaultSeewoClient(new Account(seewoConfig.getAppId(), seewoConfig.getAppSecret()));
        HomeSchoolServiceSendNoteToKidParam param = new HomeSchoolServiceSendNoteToKidParam();
        //响应体，MimeType为 application/json
        HomeSchoolServiceSendNoteToKidParam.RequestBody requestBody = HomeSchoolServiceSendNoteToKidParam.RequestBody.builder()
                .build();
        param.setRequestBody(requestBody);
        //query
        HomeSchoolServiceSendNoteToKidParam.Query query = HomeSchoolServiceSendNoteToKidParam.Query.builder()
                .appId(seewoConfig.getAppId())
                .schoolUid(seewoConfig.getSchoolId())
                .senderPhone(parentPhone)
                .studentCode(studentCode)
                .type(1)
                .content(content)
                .autoRegister(0)
                .build();
        requestBody.setQuery(query);
        param.setRequestBody(requestBody);
        HomeSchoolServiceSendNoteToKidRequest request = new HomeSchoolServiceSendNoteToKidRequest(param);
        System.out.println("入参：" + request);
        //如果想要调用沙箱环境，请通过设置 request 对象的 serverUrl 属性，如：
        //request.setServerUrl("https://openapi.test.seewo.com")
        //执行请求，如果想获取到com.seewo.open.sdk.HttpResponse对象，请调用 seewoClient.execute 方法
        HomeSchoolServiceSendNoteToKidResult result = seewoClient.invoke(request);
        System.out.println("出参：" + result);
        if (!result.getMessage().equals("success")) {
            CommonResult.fail();
        }

        return CommonResult.ok();
    }

    /**
     * 获取到访代办数据
     *
     * @param userId
     * @return
     */
    @Override
    public CommonResult visitingAgencys(int currentPage, int pageCount, int userId, int type) {
        SmartUser user = smartUserService.getSmartById(userId);
        if (user == null) {
            return CommonResult.fail("当前用户数据无效，获取到访数据失败");
        }

        if (user.getIdentityId().intValue() != eIdentityStatu.Teacher.getValue()) {
            return CommonResult.fail("非教师身份无法获取到访数据");
        }

        //是否是管理员
        String whereSql = null;
        //获取的权限组数据
        List<SmartAuthorGroup> authorGroups = smartAuthorGroupService.smartAuthorGroup(user.getId());
        for (SmartAuthorGroup authorGroup : authorGroups) {
            List<String> applyIds = Arrays.asList(authorGroup.getApplyId().split(","));
            //菜单表中7是访客预约
            long appointCount = applyIds.stream().filter(e -> e.equals("7")).count();
            if (appointCount > 0) {
                whereSql = "visitor_type = 2";
                break;
            }
        }

        List<Integer> studentIds = null;
        //班主任
        if (user.getDuties().intValue() == eDuties.ClassTeacher.getValue()) {
            //班级ID
            Integer schoolClass = user.getSchoolClass();
            //获取该班级下的所有学生ID数据
            List<SmartUser> students = smartUserService.queryStudentBySchoolClass(user.getSchoolClass());

            if (students == null) {
                return CommonResult.fail("当前身份下不存在学生信息");
            }

            studentIds = students.stream().map(SmartUser::getId).collect(Collectors.toList());
        }

        PageUtils<SmartVisitor> result = new PageUtils<SmartVisitor>(null, 0, pageCount, currentPage);

        if (whereSql == null && studentIds == null) {
            return CommonResult.ok(result);
        }

        result = smartVisitorService.queryVisitorPageDatas(currentPage, pageCount, type, studentIds, studentIds != null && whereSql != null ? "or " + whereSql : whereSql);

        return CommonResult.ok(result);
    }

    @Override
    public TurnOnDeviceVo turnOnTheDevice(turnOnTheDeviceRequest data) throws JsonProcessingException {
        TurnOnDeviceVo result = new TurnOnDeviceVo();

        //region 参数判断
        if (data == null) {
            result.setResultcode(2);
            result.setMessage("扫码参数不能为空");
            result.setActionName("qrCodePush");
            return result;
        }

        if (data.getActionName() == null) {
            result.setResultcode(2);
            result.setMessage("指令不能为空");
            result.setActionName("qrCodePush");
            return result;
        }

        if (!data.getActionName().equals("qrCodePush")) {
            result.setResultcode(2);
            result.setMessage("指令错误");
            result.setActionName("qrCodePush");
            return result;
        }

        if (data.getData() == null) {
            result.setResultcode(2);
            result.setMessage("二维码内容不能为空");
            result.setActionName("qrCodePush");
            return result;
        }

        ObjectMapper objectMapper = new ObjectMapper();
        qrCodeVo codeVo = objectMapper.readValue(data.getData(), qrCodeVo.class);
        if (codeVo == null) {
            result.setResultcode(2);
            result.setMessage("二维码内容不能为空");
            result.setActionName("qrCodePush");
            return result;
        }

        if (codeVo.getQrCode() == null) {
            result.setResultcode(2);
            result.setMessage("二维码内容不能为空");
            result.setActionName("qrCodePush");
            return result;
        }

        if (data.getDeviceno() == null) {
            result.setResultcode(2);
            result.setMessage("设备编号不能为空");
            result.setActionName("qrCodePush");
            return result;
        }

        if (data.getVersion() == null) {
            result.setResultcode(2);
            result.setMessage("版本不能为空");
            result.setActionName("qrCodePush");
            return result;
        }
        //endregion

        //解码逻辑
        QrcodeImageVo qiv = objectMapper.readValue(codeVo.getQrCode(), QrcodeImageVo.class);

        SmartUser user = smartUserService.getSmartById(qiv.getId());
        if (user == null) {
            result.setResultcode(2);
            result.setMessage("用户身份无效，刷码失败");
            result.setActionName("qrCodePush");
            return result;
        }

        //目前二维码一分钟内有效
        //过期：（时间戳 + 有效期分钟数）<= 当前时间
        //时间戳转时间
        Date dateNow = TimeExchange.StringToDate(TimeExchange.TimeRangeI10(qiv.getTimestamp(), 1), "yyyy-MM-dd HH:mm:ss");
        if (dateNow.compareTo(new Date()) < 0) {
            result.setResultcode(2);
            result.setMessage("身份码已过期");
            result.setActionName("qrCodePush");
            return result;
        }

        //成功后将刷码记录存储到数据表中
        SmartQrcode sq = new SmartQrcode();
        sq.setUserId(0);
        sq.setSourceCode(data.getData());
        sq.setIsSuccess(1);


        int insertResult = smartQrcodeService.insertSmartQrcode(sq);
        if (insertResult <= 0) {
            result.setResultcode(2);
            result.setMessage("新增刷码记录失败");
            result.setActionName("qrCodePush");
            return result;
        }

        result.setResultcode(1);
        result.setMessage("成功");
        result.setActionName("qrCodePush");
        return result;
    }


}

