package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SendSmsUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.BomanReservatConfigTime;
import com.ruoyi.system.mapper.BomanReservatConfigTimeMapper;
import com.ruoyi.system.mapper.ReceptionPersonnelMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.logging.log4j.util.Base64Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.BomanReservatMapper;
import com.ruoyi.system.domain.BomanReservat;
import com.ruoyi.system.service.IBomanReservatService;
import sun.misc.BASE64Encoder;

import static com.ruoyi.common.constant.Constants.RESERVAT_PERSONNEL_NUM;

/**
 * 陵园预约Service业务层处理
 *
 * @author ruoyi
 * @date 2023-11-02
 */
@Service
public class BomanReservatServiceImpl implements IBomanReservatService {
    @Autowired
    private BomanReservatMapper bomanReservatMapper;

    @Autowired
    private BomanReservatConfigTimeMapper bomanReservatConfigTimeMapper;
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ReceptionPersonnelMapper receptionPersonnelMapper;

    /**
     * 查询陵园预约
     *
     * @param reservatId 陵园预约主键
     * @return 陵园预约
     */
    @Override
    public BomanReservat selectBomanReservatByReservatId(Long reservatId) {
        return bomanReservatMapper.selectBomanReservatByReservatId(reservatId);
    }

    /**
     * 查询陵园预约列表
     *
     * @param bomanReservat 陵园预约
     * @return 陵园预约
     */
    @Override
    public List<BomanReservat> selectBomanReservatList(BomanReservat bomanReservat) {
        String dataType = bomanReservat.getDataType();
        if ("1".equals(dataType)) {
            bomanReservat.setVisitDate(DateUtils.getDate());
        }
        if ("2".equals(dataType)) {
            bomanReservat.setVisitDate(DateUtils.getDateByDays(-1));
        }
        return bomanReservatMapper.selectBomanReservatList(bomanReservat);
    }

    /**
     * 新增陵园预约
     *
     * @param bomanReservat 陵园预约
     * @return 结果
     */
    @Override
    public int insertBomanReservat(BomanReservat bomanReservat) {
        Long reservatConfigTimeId = bomanReservat.getReservatConfigTimeId();
        //查询可预约人数
        BomanReservatConfigTime bomanReservatConfigTime = bomanReservatConfigTimeMapper.selectBomanReservatConfigTimeByReservatConfigTimeId(reservatConfigTimeId);
        //组装key
        //去redis找对应日期,对应时段id的预约数量 reservat_num:2023-10-10_1
        String key = Constants.RESERVAT_NUM + bomanReservat.getVisitDate() + "_" + reservatConfigTimeId;
        //已经预约人数
        Object reservatNum = redisCache.getCacheObject(key);
        //最新预约人数
        long numNew = Long.parseLong(bomanReservat.getVisitNum());
        if (ObjectUtils.isNotEmpty(reservatNum)) {
            //最新预约人数 = 已经预约人数 + 新增预约人数
            numNew = (long) reservatNum + numNew;
        }
        //是否超过最大可预约人数
        //判断已预约人数+新增预约人数=是否大于可预约人数
        //如果 x==y 返回0；x<y 返回负数(-1)；x>y 返回正数(1)
        if (NumberUtils.compare(bomanReservatConfigTime.getReservatConfigNum(), numNew) < 0) {
            return 0;
        }


        bomanReservat.setCreateTime(DateUtils.getNowDate());
        String reservatType = bomanReservat.getReservatType();
        if ("2".equals(reservatType)) {
            bomanReservat.setVisitType("3");
        } else {
            //如果是团队,判断是否需要接待
            if ("Y".equals(bomanReservat.getIsReception())){
                BomanReservat br = new BomanReservat();
                br.setReservatConfigTimeId(bomanReservat.getReservatConfigTimeId());
                br.setVisitType("3");
                br.setVisitDate(bomanReservat.getVisitDate());
                //查询一下,该时段接待人员是否已满
                List<BomanReservat> bomanReservats = bomanReservatMapper.selectBomanReservatList(br);
                //再去查询接待人员数量
                int num = receptionPersonnelMapper.selectReceptionPersonnelCount();
                if (bomanReservats != null){
                    if (bomanReservats.size() >= num ){
                        return 0;
                    }
                    if (bomanReservats.size() + 1 == num){
                        //插入redis该时段接待人员已满
                        String keyPersonnel = Constants.RESERVAT_PERSONNEL_NUM + bomanReservat.getVisitDate() + "_" + reservatConfigTimeId;
                        redisCache.setCacheObject(keyPersonnel,"Y",24, TimeUnit.HOURS);
                    }
                }
            }
            //获取管理员账户
            SysUser sysUser = new SysUser();
            sysUser.setUserType("lyManage");
            List<SysUser> sysUsers = userMapper.selectUserList(sysUser);
            if (sysUsers != null && sysUsers.size() > 0) {
                String phonenumber = sysUsers.get(0).getPhonenumber();
                //团队预约,给管理员发送短信
                //陵园预约通知 = SMS_464376020
                SendSmsUtils.sendSms(phonenumber, "SMS_464376020", null);
                System.out.println("给(" + phonenumber + ")陵园管理员发送了("+bomanReservat.getVisitPhone()+")申请预约的短信");
            }

        }
        int i = bomanReservatMapper.insertBomanReservat(bomanReservat);
        if (i > 0) {
            i = Math.toIntExact(bomanReservat.getReservatId());
        }
        //新增预约往redis中存放数据
        redisCache.setCacheObject(key, numNew,24, TimeUnit.HOURS);
        return i;
    }

    /**
     * 修改陵园预约
     *
     * @param bomanReservat 陵园预约
     * @return 结果
     */
    @Override
    public AjaxResult updateBomanReservat(BomanReservat bomanReservat) {
        //判断该接待人员当前时段是否已经被选择过, 需要传入预约时段id
        if (bomanReservat.getReceptionId() != null){
            List<BomanReservat> bomanReservats = bomanReservatMapper.selectBomanReservatList(bomanReservat);
            if (bomanReservats != null && bomanReservats.size() > 0){
                return AjaxResult.error("当前讲解员已被选择");
            }
        }
        bomanReservat.setUpdateTime(DateUtils.getNowDate());
        return bomanReservatMapper.updateBomanReservat(bomanReservat)> 0 ? AjaxResult.success() : AjaxResult.error("预约人数已满");
    }

    /**
     * 批量删除陵园预约
     *
     * @param reservatIds 需要删除的陵园预约主键
     * @return 结果
     */
    @Override
    public int deleteBomanReservatByReservatIds(Long[] reservatIds) {
        //取消预约,需要修改redis中的预约人数
        for (Long reservatId : reservatIds) {
            BomanReservat bomanReservat = bomanReservatMapper.selectBomanReservatByReservatId(reservatId);
            Long reservatConfigTimeId = bomanReservat.getReservatConfigTimeId();
            String visitNum = bomanReservat.getVisitNum();
            //去redis找对应日期,对应时段id的预约数量 reservat_num:2023-10-10_1
            String key = Constants.RESERVAT_NUM + bomanReservat.getVisitDate() + "_" + reservatConfigTimeId;
            Object reservatNum = redisCache.getCacheObject(key);
            if (ObjectUtils.isNotEmpty(reservatNum)) {
                long reservatNumNew = (long) reservatNum - Long.parseLong(visitNum);
                if (reservatNumNew < 0) {
                    reservatNumNew = 0;
                }
                redisCache.setCacheObject(key, reservatNumNew,24, TimeUnit.HOURS);
            }
            //判断是不是团队需要接待的续约
            if ("1".equals(bomanReservat.getReservatType()) && "Y".equals(bomanReservat.getIsReception())){
                String keyPersonnel = Constants.RESERVAT_PERSONNEL_NUM + bomanReservat.getVisitDate() + "_" + reservatConfigTimeId;
                redisCache.deleteObject(keyPersonnel);
            }
        }
        return bomanReservatMapper.deleteBomanReservatByReservatIds(reservatIds);
    }

    /**
     * 删除陵园预约信息
     *
     * @param reservatId 陵园预约主键
     * @return 结果
     */
    @Override
    public int deleteBomanReservatByReservatId(Long reservatId) {
        return bomanReservatMapper.deleteBomanReservatByReservatId(reservatId);
    }

    @Override
    public AjaxResult examine(BomanReservat bomanReservat) {

        BomanReservat reservat = bomanReservatMapper.selectBomanReservatByReservatId(bomanReservat.getReservatId());

        Long reservatConfigTimeId = reservat.getReservatConfigTimeId();

        if ("3".equals(bomanReservat.getVisitType()) && "Y".equals(reservat.getIsReception()) && StringUtils.isEmpty(reservat.getReceptionName())) {
            return AjaxResult.error("请先分配接待人员");
        }
        //拒绝,释放名额
        if ("2".equals(bomanReservat.getVisitType())) {
            String visitNum = reservat.getVisitNum();
            //去redis找对应日期,对应时段id的预约数量 reservat_num:2023-10-10_1
            String key = Constants.RESERVAT_NUM + reservat.getVisitDate() + "_" + reservatConfigTimeId;
            Object numString = redisCache.getCacheObject(key);
            long num = (long) numString - Long.parseLong(visitNum);
            redisCache.setCacheObject(key, num < 0 ? 0 : num,24, TimeUnit.HOURS);
            String keyPersonnel = Constants.RESERVAT_PERSONNEL_NUM + reservat.getVisitDate() + "_" + reservatConfigTimeId;
            redisCache.deleteObject(keyPersonnel);
        }
        bomanReservat.setUpdateTime(DateUtils.getNowDate());
        int i = bomanReservatMapper.updateBomanReservat(bomanReservat);

        //审核通过给团队发送通过短信
        if ("3".equals(bomanReservat.getVisitType())) {
            String visitPhone = reservat.getVisitPhone();
            JSONObject jsonObject = new JSONObject();
            String code = Base64.getEncoder().encodeToString(String.valueOf(reservat.getReservatId()).getBytes(StandardCharsets.UTF_8));
            jsonObject.put("code", code);
            //陵园预约通过通知 = SMS_464336030
            SendSmsUtils.sendSms(visitPhone, "SMS_464336030", jsonObject.toString());
            System.out.println("给(" + visitPhone + ")团队发送了审核通过的短信");
        }
        return i > 0 ? AjaxResult.success() : AjaxResult.error();
    }
    /**
     * 预约首页统计
     *
     * @param
     * @return
     */
    @Override
    public AjaxResult indexStatistics(BomanReservat bomanReservat) {
        Map<String, Object> map = new HashMap<>(4);
        map.put("canGuan" , 0);
        map.put("yuYue" , 0);
        map.put("todayYuYue" , 0);
        map.put("todayCanGuan" , 0);
        List<BomanReservat> bomanReservats = bomanReservatMapper.selectBomanReservatList(bomanReservat);
        if (bomanReservats != null && bomanReservats.size() > 0) {
            //来访数
            long canGuan = bomanReservats.stream().filter(s -> "2".equals(s.getVisitStatus())).count();
            long todayYuYue = bomanReservats.stream().filter(s -> DateUtils.getDate().equals(s.getVisitDate())).count();
            long todayCanGuan = bomanReservats.stream().filter(s -> DateUtils.getDate().equals(s.getVisitDate())).filter(s -> "2".equals(s.getVisitStatus())).count();
            map.put("canGuan" , canGuan);
            map.put("yuYue" , bomanReservats.size());
            map.put("todayYuYue" , todayYuYue);
            map.put("todayCanGuan" , todayCanGuan);
        }
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult verification(Long reservatId) {
        BomanReservat reservat = bomanReservatMapper.selectBomanReservatByReservatId(reservatId);
        if (!"3".equals(reservat.getVisitType())){
            return AjaxResult.error("当前预约未通过,禁止核销");
        }
        if ("2".equals(reservat.getVisitStatus())) {
            return AjaxResult.error("当前预约已核销，请勿重复操作。");
        }
        BomanReservat bomanReservat = new BomanReservat();
        bomanReservat.setReservatId(reservatId);
        bomanReservat.setVisitStatus("2");
        int i = bomanReservatMapper.updateBomanReservat(bomanReservat);
        return i > 0 ? AjaxResult.success() : AjaxResult.error();
    }


    /**
     * 陵园实时参观统计
     */
    @Override
    public AjaxResult realTime() {
        // todo

        String configKey = "lyssllsj";
        String configKey_1 = "lyssllsj_1";
        String configValue = Convert.toStr(redisCache.getCacheObject(configKey));
        String configValue_1 = Convert.toStr(redisCache.getCacheObject(configKey_1));
        if(StringUtils.isEmpty(configValue) || "0".equals(configValue)){
            configValue = "0";
        }
        if(StringUtils.isEmpty(configValue_1) || "0".equals(configValue_1)){
            configValue_1 = "0";
        }


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("scale" , "0%");

        if(!"0".equals(configValue) && !"0".equals(configValue_1)){
            BigDecimal num1 = new BigDecimal("configValue");
            BigDecimal num2 = new BigDecimal("configValue_1");
            double result = Double.parseDouble(((num1.divide(num2)).setScale(2,BigDecimal.ROUND_HALF_UP)).toString());
            DecimalFormat decimalFormat = new DecimalFormat("0%"); // 创建DecimalFormat对象并设置格式化模式为"0%"
            String percentage = decimalFormat.format((result * 100)); // 使用DecimalFormat对象进行格式化操作
            resultMap.put("scale" , percentage);
        }

        //今天比昨天新增多少人
        resultMap.put("addNum" , Long.parseLong(configValue)-Long.parseLong(configValue_1));
        //昨天人数
        resultMap.put("current" , configValue_1);
        //今天人数
        resultMap.put("total" , configValue);
        return AjaxResult.success(resultMap);
    }

    @Override
    public AjaxResult people() {
        Map<String, Object> map = new HashMap<>();

        String time = DateUtils.getDate();
        //获取当前年
        String year = time.split("-")[0];
        //查询当前年预约人数
        List<BomanReservat> bomanReservatYearList = bomanReservatMapper.selectBomanReservatbyYear(year);
        long yearYy = 0;
        //查询当前月预约人数
        long monthYy = 0;
        //查询当前天预约人数
        long todayYy = 0;
        for (BomanReservat bomanReservat : bomanReservatYearList) {
            yearYy = yearYy + Long.parseLong(bomanReservat.getVisitNum());
            if(bomanReservat.getVisitDate().contains(time.substring(0,time.lastIndexOf("-")))){
                monthYy = monthYy + Long.parseLong(bomanReservat.getVisitNum());
            }
            if (bomanReservat.getVisitDate().equals(time)) {
                todayYy = todayYy + Long.parseLong(bomanReservat.getVisitNum());
            }
        }
        map.put("yearYy" , yearYy);
        map.put("monthYy" , monthYy);
        map.put("todayYy" , todayYy);
        //todo 今日参观人数
        map.put("todayVisit" , 10);

        Map<String, Object> sevenMap = new HashMap<>();
        //获取近7天的数组
        List<String> sevenDate = getSevenDate();
        //获取7天中最早的一天
        String first = sevenDate.get(0);
        //查询七天中的数据
        List<BomanReservat> bomanReservatSevenList = bomanReservatMapper.selectBomanReservatbySeven(first, time);
        List<Long> zrsList = new ArrayList<>();
        List<Long> skList = new ArrayList<>();
        List<Long> tdList = new ArrayList<>();
        Long zrs = 0L;
        Long sk = 0L;
        Long td = 0L;
        for (int i = 0; i < sevenDate.size(); i++) {
            for (BomanReservat bomanReservat : bomanReservatSevenList) {
                if (bomanReservat.getVisitDate().equals(sevenDate.get(i))) {
                    zrs = zrs + Long.parseLong(bomanReservat.getVisitNum());
                    if ("1".equals(bomanReservat.getReservatType())) {
                        td = td + Long.parseLong(bomanReservat.getVisitNum());
                    } else {
                        sk = sk + Long.parseLong(bomanReservat.getVisitNum());
                    }
                }
            }
            zrsList.add(zrs);
            skList.add(sk);
            tdList.add(td);
            //循环完一轮之后重置
            zrs = 0L;
            sk = 0L;
            td = 0L;
        }

        sevenMap.put("date" , sevenDate);
        sevenMap.put("zrs" , zrsList);
        sevenMap.put("sk" , skList);
        sevenMap.put("td" , tdList);

        map.put("sevenMap" , sevenMap);
        return AjaxResult.success(map);
    }


    //获取近七天日期
    public static List<String> getSevenDate() {
        List<String> dateList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 6; i >= 0; i--) {
            Date date = DateUtils.addDays(new Date(), -i);
            String formatDate = sdf.format(date);
            dateList.add(formatDate);
        }
        return dateList;
    }

}
