package org.dromara.system.service.impl.reservat;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.SneakyThrows;
import org.dromara.common.core.domain.AjaxResult;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.comm.utils.SmsUtil;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.provider.enumerate.SupplierType;
import org.dromara.system.domain.reservat.XiaoyuanReservat;
import org.dromara.system.domain.reservat.XiaoyuanReservatConfig;
import org.dromara.system.domain.reservat.bo.XiaoyuanReservatBo;
import org.dromara.system.domain.reservat.vo.XiaoyuanReservatConfigVo;
import org.dromara.system.domain.reservat.vo.XiaoyuanReservatVo;
import org.dromara.system.mapper.reservat.XiaoyuanReservatConfigMapper;
import org.dromara.system.mapper.reservat.XiaoyuanReservatMapper;
import org.dromara.system.service.reservat.IXiaoyuanReservatService;
import org.dromara.system.utils.SendSmsUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 校园预约Service业务层处理
 *
 * @author boman
 * @date 2023-09-12
 */
@RequiredArgsConstructor
@Service
public class XiaoyuanReservatServiceImpl implements IXiaoyuanReservatService {

    private final XiaoyuanReservatMapper baseMapper;

    private final XiaoyuanReservatConfigMapper xiaoyuanReservatConfigMapper;

    /**
     * 查询校园预约
     */
    @Override
    public XiaoyuanReservatVo queryById(Long reservatId){
        return baseMapper.selectVoById(reservatId);
    }

    /**
     * 查询校园预约列表
     */
    @Override
    public TableDataInfo<XiaoyuanReservatVo> queryPageList(XiaoyuanReservatBo bo, PageQuery pageQuery) {
        LoginUser user = LoginHelper.getLoginUser();
        List<RoleDTO> roles = user.getRoles();
        Boolean bl = false;
        for (RoleDTO role : roles) {
            if("teacher".equals(role.getRoleKey())){
                bl = true;
            }
        }
        if(bl){
            bo.setTeacherPhone(user.getUsername());
        }
        LambdaQueryWrapper<XiaoyuanReservat> lqw = buildQueryWrapper(bo);
        Page<XiaoyuanReservatVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询校园预约列表
     */
    @Override
    public List<XiaoyuanReservatVo> queryList(XiaoyuanReservatBo bo) {
        LambdaQueryWrapper<XiaoyuanReservat> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<XiaoyuanReservat> buildQueryWrapper(XiaoyuanReservatBo bo) {
        LambdaQueryWrapper<XiaoyuanReservat> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getReservatId() != null && bo.getReservatId() != 0L, XiaoyuanReservat::getReservatId, bo.getReservatId());
        lqw.like(StringUtils.isNotBlank(bo.getTeacherName()), XiaoyuanReservat::getTeacherName, bo.getTeacherName());
        lqw.eq(StringUtils.isNotBlank(bo.getTeacherPhone()), XiaoyuanReservat::getTeacherPhone, bo.getTeacherPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getTenantId()), XiaoyuanReservat::getTenantId, bo.getTenantId());
        lqw.like(StringUtils.isNotBlank(bo.getVisitName()), XiaoyuanReservat::getVisitName, bo.getVisitName());
        lqw.eq(StringUtils.isNotBlank(bo.getVisitPhone()), XiaoyuanReservat::getVisitPhone, bo.getVisitPhone());
        lqw.eq(bo.getVisitTime() != null, XiaoyuanReservat::getVisitTime, bo.getVisitTime());
        lqw.eq(bo.getVisitDateTime() != null, XiaoyuanReservat::getVisitDateTime, bo.getVisitDateTime());
        lqw.eq(StringUtils.isNotBlank(bo.getVisitType()), XiaoyuanReservat::getVisitType, bo.getVisitType());
        lqw.eq(StringUtils.isNotBlank(bo.getVisitStatus()), XiaoyuanReservat::getVisitStatus, bo.getVisitStatus());
        String dataType = bo.getDataType();
        if ("1".equals(dataType)){
            bo.setVisitDate(DateUtils.getDate());
            lqw.eq(bo.getVisitDate() != null, XiaoyuanReservat::getVisitDate, bo.getVisitDate());
        }
        if ("2".equals(dataType)){
            bo.setVisitDate(DateUtils.getDateByDays(-1));
            lqw.eq(bo.getVisitDate() != null, XiaoyuanReservat::getVisitDate, bo.getVisitDate());
        }


        if ("3".equals(dataType)){
            lqw.apply("visit_date >= DATE_SUB(NOW(), INTERVAL 7 DAY)");
        }
        if ("4".equals(dataType)){
            lqw.apply("visit_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)");
        }
        lqw.orderByDesc(XiaoyuanReservat::getCreateTime);
        return lqw;
    }

    /**
     * 新增校园预约
     */
    @Override
    public Boolean insertByBo(XiaoyuanReservatBo bo) {
        XiaoyuanReservat add = MapstructUtils.convert(bo, XiaoyuanReservat.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setReservatId(add.getReservatId());
        }
        return flag;
    }

    /**
     * 修改校园预约
     */
    @Override
    public Boolean updateByBo(XiaoyuanReservatBo bo) {
        XiaoyuanReservat update = MapstructUtils.convert(bo, XiaoyuanReservat.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(XiaoyuanReservat entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除校园预约
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据教职工手机号查询可预约的时间
     */
    @SneakyThrows
    @Override
    public AjaxResult subscribe(XiaoyuanReservatBo bo) {
        LambdaQueryWrapper<XiaoyuanReservatConfig> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTeacherPhone()), XiaoyuanReservatConfig::getTeacherPhone, bo.getTeacherPhone());
        XiaoyuanReservatConfigVo xiaoyuanReservatConfigVo = xiaoyuanReservatConfigMapper.selectVoOne(lqw);
        Map map =new HashMap();
        map.put("reservatConfigTimeAmBegin","");
        map.put("reservatConfigTimeAmEnd","");
        map.put("reservatConfigTimePmBegin","");
        map.put("reservatConfigTimePmEnd","");
        if (xiaoyuanReservatConfigVo != null){
            map.put("reservatConfigTimeAmBegin",xiaoyuanReservatConfigVo.getReservatConfigTimeAmBegin());
            map.put("reservatConfigTimeAmEnd",xiaoyuanReservatConfigVo.getReservatConfigTimeAmEnd());
            map.put("reservatConfigTimePmBegin",xiaoyuanReservatConfigVo.getReservatConfigTimePmBegin());
            map.put("reservatConfigTimePmEnd",xiaoyuanReservatConfigVo.getReservatConfigTimePmEnd());
            //获取预约的年月
            String visitDate = bo.getVisitDate();
            List<String> monthFullDay = DateUtils.getMonthFullDay(DateUtils.parseDate(visitDate));
            LambdaQueryWrapper<XiaoyuanReservat> lqwr = Wrappers.lambdaQuery();
            JSONArray jsonArray = new JSONArray();
            if (monthFullDay.size() > 0){
                //判断日期是星期几,是否可以预约
                for (String date : monthFullDay) {
                    JSONObject jsonObject = new JSONObject();
                    int week = DateUtils.dayForWeek(date);
                    jsonObject.put("date",date);
                    jsonObject.put("title","不可约");
                    String reservatConfigDate = xiaoyuanReservatConfigVo.getReservatConfigDate();
                    if (reservatConfigDate.contains(String.valueOf(week))){
                        jsonObject.put("title","可预约");
                        //包含去查询改天是否被预约满
                        lqwr.eq(StringUtils.isNotBlank(bo.getTeacherPhone()), XiaoyuanReservat::getTeacherPhone, bo.getTeacherPhone());
                        lqwr.eq(XiaoyuanReservat::getVisitDate, date);
                        List<XiaoyuanReservatVo> xiaoyuanReservatVos = baseMapper.selectVoList(lqwr);
                        if (xiaoyuanReservatVos != null && xiaoyuanReservatVos.size() > 0){
                            //判断是否大于次数
                            Long reservatConfigNum = xiaoyuanReservatConfigVo.getReservatConfigNum();
                            if (xiaoyuanReservatVos.size() > reservatConfigNum){
                                //说明约满
                                jsonObject.put("title","已约满");
                            }
                        }
                    }
                    jsonArray.add(jsonObject);
                }
                map.put("signList",jsonArray);
            }
            return AjaxResult.success(map);
        }
        return AjaxResult.error("该用户暂不可预约");

    }


    /**
     * 预约首页统计
     */
    @Override
    public AjaxResult indexStatistics(XiaoyuanReservatBo bo) {
        Map<String,Object> map = new HashMap<>(4);
        map.put("laiFang",0);
        map.put("yuYue",0);
        map.put("todayV",0);
        map.put("todayLaiFang",0);
        LambdaQueryWrapper<XiaoyuanReservat> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTenantId()), XiaoyuanReservat::getTenantId, bo.getTenantId());
        List<XiaoyuanReservat> xiaoyuanReservats = baseMapper.selectList(lqw);
        if (xiaoyuanReservats != null && xiaoyuanReservats.size() > 0){
            //来访数
            long laiFang = xiaoyuanReservats.stream().filter(s -> "2".equals(s.getVisitStatus())).count();
            long todayV = xiaoyuanReservats.stream().filter(s -> DateUtils.getDate().equals(s.getVisitDate())).count();
            long todayLaiFang = xiaoyuanReservats.stream().filter(s -> DateUtils.getDate().equals(s.getVisitDate())).filter(s -> "2".equals(s.getVisitStatus())).count();
            map.put("laiFang",laiFang);
            map.put("yuYue",xiaoyuanReservats.size());
            map.put("todayV",todayV);
            map.put("todayLaiFang",todayLaiFang);
        }
        return AjaxResult.success(map);
    }

    /**
     * 校园预约核销
     *
     * @param reservatId
     */
    @Override
    public R<Void> cav(Long reservatId) {
        LoginUser user = LoginHelper.getLoginUser();
        //查询数据库是否存在数据
        XiaoyuanReservatBo bo = new XiaoyuanReservatBo();
        bo.setReservatId(reservatId);
        bo.setTenantId(user.getTenantId());
        LambdaQueryWrapper<XiaoyuanReservat> lqw = buildQueryWrapper(bo);
        List<XiaoyuanReservatVo> reservatVoList = baseMapper.selectVoList(lqw);
        if(reservatVoList==null || reservatVoList.size()<=0){
            return R.fail("无当前学校预约，核销失败");
        }
        int i = 0;
        for (XiaoyuanReservatVo xiaoyuanReservatVo : reservatVoList) {
            if("2".equals(xiaoyuanReservatVo.getVisitStatus())){
                return R.ok("核销失败");
            }
            XiaoyuanReservat update = new XiaoyuanReservat();
            update.setReservatId(xiaoyuanReservatVo.getReservatId());
            update.setVisitStatus("2");
            i = baseMapper.updateById(update);
        }
        if(i>0){
            return R.ok("核销成功");
        }else{
            return R.fail("核销失败");
        }
    }

    @Override
    public Boolean shByBo(XiaoyuanReservatBo bo) {
        String templateCode = "";
        if("2".equals(bo.getVisitType())){
            templateCode = "SMS_463655370";
        }else if ("3".equals(bo.getVisitType())){
             templateCode = "SMS_463685073";
        }
        //"{\"code\":\"1111\"}"
        SendSmsUtils.sendSms(bo.getTeacherPhone(),templateCode,"{\"link\":\""+bo.getReservatId()+"\"}");
        XiaoyuanReservat update = MapstructUtils.convert(bo, XiaoyuanReservat.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }
}
