package org.jeecg.modules.system.app.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.app.form.QueryByOrgCodeForm;
import org.jeecg.modules.quartz.utils.HolidayUtil;
import org.jeecg.modules.system.app.dto.*;
import org.jeecg.modules.system.app.entity.*;
import org.jeecg.modules.system.app.enums.SitePlaceTypeEnum;
import org.jeecg.modules.system.app.mapper.*;
import org.jeecg.modules.system.app.service.IAppSitePlaceService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static org.jeecg.common.constant.CommonConstant.SC_INTERNAL_SERVER_ERROR_500;

/**
 * @Description: 商户场所表
 * @Author: jeecg-boot
 * @Date: 2025-07-09
 * @Version: V1.0
 */
@Slf4j
@Service
public class AppSitePlaceServiceImpl extends ServiceImpl<AppSitePlaceMapper, AppSitePlace> implements IAppSitePlaceService {
    @Resource
    private AppSitePriceRulesMapper appSitePriceRulesMapper;
    @Resource
    private AppTeachingTimeMapper appTeachingTimeMapper;
    @Resource
    private AppSiteMapper appSiteMapper;
    @Resource
    private AppCategoryMapper appCategoryMapper;
    @Resource
    private AppSiteRuleTimeMapper appSiteRuleTimeMapper;

    //学校 一对多

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveSchool(AppSitePlaceSchoolDTO placeDTO) {
        AppSitePlaceCuDTO appSitePlaceCuDTO = placeDTO.getAppSitePlaceCuDTO();
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (null == appSitePlaceCuDTO.getSiteId())
            throw new JeecgBootException("商户补充信息id不能为空", SC_INTERNAL_SERVER_ERROR_500);
        AppSite site = appSiteMapper.selectById(appSitePlaceCuDTO.getSiteId());
        AppSitePlace appSitePlace = new AppSitePlace();
        BeanUtils.copyProperties(appSitePlaceCuDTO, appSitePlace);
        appSitePlace.setOrgCode(site.getOrgCode());
        appSitePlace.setTenantId(site.getTenantId());
        appSitePlace.setSiteId(site.getId());
        appSitePlace.setType(SitePlaceTypeEnum.SCHOOL.getCode());
//        //时间段提取拼接
//        List<AppSiteRuleDTO> siteRuleDTOS = placeDTO.getSiteRuleDTOS();
//
//        List<String> teachingDay = new ArrayList<>();
//        List<String> noTeachingDay = new ArrayList<>();
//        if (!siteRuleDTOS.isEmpty()) {
//            siteRuleDTOS.forEach(dto -> {
//                if (dto.getIsTeaching() == 0) {
//                    teachingDay.add(dto.getStartTime() + "-" + dto.getEndTime());
//                } else {
//                    noTeachingDay.add(dto.getStartTime() + "-" + dto.getEndTime());
//                }
//            });
//        }
//        site.setTeachingDay(String.join(",", teachingDay));
//        site.setNoTeachingDay(String.join(",", noTeachingDay));
//        int updateById = appSiteMapper.updateById(site);
//        if (updateById < 1) {
//            throw new JeecgBootException("学校补充信息更新失败");
//        }
//        int insert = baseMapper.insert(appSitePlace);
//        if (insert < 1) {
//            throw new JeecgBootException("学校场所信息保存失败");
//        }
//        siteRuleDTOS.forEach(rule -> {
//            AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
//            BeanUtils.copyProperties(rule, appSitePriceRules);
//            appSitePriceRules.setSitePlaceId(appSitePlace.getId());
//            appSitePriceRules.setOrgCode(appSitePlace.getOrgCode());
//            appSitePriceRules.setTenantId(appSitePlace.getTenantId());
//            int savePriceResult = appSitePriceRulesMapper.insert(appSitePriceRules);
//            if (savePriceResult < 1) {
//                throw new JeecgBootException("场所价格规则保存失败", SC_INTERNAL_SERVER_ERROR_500);
//            }
//        });

        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editSchool(AppSitePlaceSchoolDTO placeDTO) {
        AppSitePlaceCuDTO appSitePlaceCuDTO = placeDTO.getAppSitePlaceCuDTO();
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (null == appSitePlaceCuDTO.getSiteId())
            throw new JeecgBootException("商户补充信息id不能为空", SC_INTERNAL_SERVER_ERROR_500);
        AppSite site = appSiteMapper.selectById(appSitePlaceCuDTO.getSiteId());
        AppSitePlace dbPlace = baseMapper.selectById(appSitePlaceCuDTO.getSiteId());
        if (null == dbPlace) throw new JeecgBootException("数据不存在", SC_INTERNAL_SERVER_ERROR_500);
        //部门校验
        //        checkPermission(dbPlace, sysUser);
        AppSitePlace appSitePlace = new AppSitePlace();
        BeanUtils.copyProperties(appSitePlaceCuDTO, appSitePlace);
        //不许更改项赋值
        appSitePlace.setOrgCode(site.getOrgCode());
        appSitePlace.setTenantId(site.getTenantId());
        appSitePlace.setSiteId(site.getId());
        int update = baseMapper.updateById(appSitePlace);
        if (update < 1) {
            throw new JeecgBootException("商户场所保存失败");
        }
        List<AppSitePriceRules> dbRulesList = appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery()
                .eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId()));
        List<AppSiteRuleDTO> siteRuleDTOS = placeDTO.getSiteRuleDTOS();
        //删除
        List<AppSitePriceRules> deleteList = dbRulesList.stream().filter(
                dbRule -> dbRule.getId() != null && siteRuleDTOS.stream().noneMatch(rule -> dbRule.getId().equals(rule.getId()))).collect(Collectors.toList());
        deleteList.forEach(
                dbRule -> {
                    int deleteResult = appSitePriceRulesMapper.deleteById(dbRule.getId());
                    if (deleteResult < 1) {
                        throw new JeecgBootException("场所价格规则删除失败");
                    }
                }
        );
        //保存
        List<AppSitePriceRules> addList = siteRuleDTOS.stream().filter(rule -> rule.getId() == null).map(ruleDTO -> {
            AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
            BeanUtils.copyProperties(ruleDTO, appSitePriceRules);
            appSitePriceRules.setOrgCode(appSitePlace.getOrgCode());
            appSitePriceRules.setTenantId(appSitePlace.getTenantId());
            appSitePriceRules.setSitePlaceId(appSitePlace.getId());
            return appSitePriceRules;
        }).collect(Collectors.toList());
        addList.forEach(appSitePriceRules -> {
            int saveResult = appSitePriceRulesMapper.insert(appSitePriceRules);
            if (saveResult < 1) {
                throw new JeecgBootException("场所价格规则保存失败", SC_INTERNAL_SERVER_ERROR_500);
            }
        });
        //更新
        List<AppSitePriceRules> updateList = siteRuleDTOS.stream().filter(
                rule -> rule.getId() != null && dbRulesList.stream().anyMatch(
                        dbRule -> dbRule.getId().equals(rule.getId()))).map(ruleDto -> {
            AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
            BeanUtils.copyProperties(ruleDto, appSitePriceRules);
            appSitePriceRules.setSitePlaceId(appSitePlace.getId());
            appSitePriceRules.setOrgCode(appSitePlace.getOrgCode());
            appSitePriceRules.setTenantId(appSitePlace.getTenantId());
            return appSitePriceRules;
        }).collect(Collectors.toList());
        updateList.forEach(rule -> {
            int updateById = appSitePriceRulesMapper.updateById(rule);
            if (updateById < 1) {
                throw new JeecgBootException("场所价格规则更新失败", SC_INTERNAL_SERVER_ERROR_500);
            }
        });
        return Boolean.TRUE;
    }

    public void remoteEditSchool(final AppSitePlaceSchoolDTO placeDTO){
        //创建一个可重用固定线程数的线程池
        ExecutorService cachedThreadPool = Executors.newFixedThreadPool(20); //固定大小的线程池

        cachedThreadPool.execute(new Runnable() {
            @Override
            public void run(){
                log.info("======>修改学校场地信息  线程<======");
                log.info("======>当前线程 NAME  ="+Thread.currentThread().getName());
                log.info("======>当前线程 ID    ="+Thread.currentThread().getId());
                log.info("======>当前线程 Count ="+Thread.activeCount());

                try {
                    Thread.sleep(1500);//线程延迟1.5秒


                } catch (NumberFormatException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        //关闭线程池
        cachedThreadPool.shutdown();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppSitePlaceSchoolDTO querySchoolById(String id) {
        AppSitePlace appSitePlace = baseMapper.selectById(id);
        if (null == appSitePlace) throw new JeecgBootException("数据不存在", SC_INTERNAL_SERVER_ERROR_500);
        AppSitePlaceCuDTO appSitePlaceCuDTO = new AppSitePlaceCuDTO();
        BeanUtils.copyProperties(appSitePlace, appSitePlaceCuDTO);
        List<AppSiteRuleDTO> collect = appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery()
                .eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId())).stream().map(
                appSitePriceRules -> {
                    AppSiteRuleDTO appSiteRuleDTO = new AppSiteRuleDTO();
                    BeanUtils.copyProperties(appSitePriceRules, appSiteRuleDTO);
                    return appSiteRuleDTO;
                }).collect(Collectors.toList());

        return new AppSitePlaceSchoolDTO(appSitePlaceCuDTO, collect);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteSchoolById(String id) {
        AppSitePlace dbPlace = baseMapper.selectById(id);
        if (null == dbPlace) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        checkPermission(dbPlace,sysUser);
        int deleteById = baseMapper.deleteById(id);
        if (deleteById < 1) throw new JeecgBootException("删除失败", SC_INTERNAL_SERVER_ERROR_500);
        int deletePriceResult = appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, id));
        if (deletePriceResult < 1) throw new JeecgBootException("场地价格规则删除失败", SC_INTERNAL_SERVER_ERROR_500);
        return Boolean.TRUE;
    }

    @Override
    public IPage<AppSitePlaceCuDTO> querySchoolPage(AppSitePlacePageDTO dto) {
        if (null == dto.getType()) throw new JeecgBootException("请选择类型", SC_INTERNAL_SERVER_ERROR_500);
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Page<AppSitePlace> page = new Page<>(dto.getPageNo(), dto.getPageSize());
        LambdaQueryWrapper<AppSitePlace> wrapper = Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getType, dto.getType())
                .like(StringUtils.isNotBlank(dto.getName()), AppSitePlace::getName, dto.getName())
                .eq(AppSitePlace::getOrgCode, loginUser.getOrgCode());
        IPage<AppSitePlace> resultPage = baseMapper.selectPage(page, wrapper);
        return resultPage.convert(record -> {
            AppSitePlaceCuDTO cuDTO = new AppSitePlaceCuDTO();
            BeanUtils.copyProperties(record, cuDTO);
            return cuDTO;
        });
    }

    // 无固定场
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addUnfixed(AppSitePlaceUnfixedDTO unsetDTO) {
//        if (null == unsetDTO.getSiteId()) throw new JeecgBootException("请选择商户门店", SC_INTERNAL_SERVER_ERROR_500);
//        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        AppSite site = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getOrgCode, unsetDTO.getOrgCode()));
        AppSitePlace appSitePlace = new AppSitePlace();
        BeanUtils.copyProperties(unsetDTO, appSitePlace);
        appSitePlace.setType(SitePlaceTypeEnum.UNFIXED.getCode());
        appSitePlace.setOrgCode(site.getOrgCode());
        appSitePlace.setTenantId(site.getTenantId());
        appSitePlace.setSiteId(site.getId());
        appSitePlace.setCategoryId(site.getCategoryId());
        int insert = baseMapper.insert(appSitePlace);
        if (insert < 1) throw new JeecgBootException("无固定场添加失败", SC_INTERNAL_SERVER_ERROR_500);
        //每新增无固定场，对应增加（7-除外日期）条场地价格规则表数据
        List<String> weekList = List.of("1", "2", "3", "4", "5", "6", "7");
        String[] split = unsetDTO.getDownTime().split(",");
        //"6,7"
        List<String> downTimes = Arrays.stream(split).collect(Collectors.toList());
        List<AppSitePriceRules> appSitePriceRulesList = new ArrayList<>();
        weekList.forEach(week -> {
            AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
            appSitePriceRules
                    .setSitePlaceId(appSitePlace.getId())
                    .setOrgCode(appSitePlace.getOrgCode())
                    .setTenantId(appSitePlace.getTenantId())
                    .setType(SitePlaceTypeEnum.UNFIXED.getCode())
                    .setOriginalPrice(unsetDTO.getOriginalPrice())
                    .setSellingPrice(unsetDTO.getSellingPrice())
                    .setDayOfWeek(week)
                    .setStatus(CommonConstant.STATUS_NORMAL)
                    .setDelFlag(CommonConstant.STATUS_NORMAL)
            ;
            if (downTimes.contains(week)) {
                appSitePriceRules.setStatus(1);
            }
            appSitePriceRulesList.add(appSitePriceRules);
        });
        int insert1 = appSitePriceRulesMapper.insertList(appSitePriceRulesList);
        if (insert1 < 1) throw new JeecgBootException("无固定场价格添加失败", SC_INTERNAL_SERVER_ERROR_500);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUnfixed(AppSitePlaceUnfixedDTO unsetDTO) {
//        if (null == unsetDTO.getSiteId())
//            throw new JeecgBootException("商户门店不能为空", SC_INTERNAL_SERVER_ERROR_500);
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        AppSitePlace dbSitePlace = baseMapper.selectById(unsetDTO.getId());
        if (null == dbSitePlace) throw new JeecgBootException("数据不存在", SC_INTERNAL_SERVER_ERROR_500);
//        checkPermission(dbSitePlace,sysUser);
        AppSite site = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getOrgCode, unsetDTO.getOrgCode()));
        AppSitePlace appSitePlace = new AppSitePlace();
        BeanUtils.copyProperties(unsetDTO, appSitePlace);
        //固定
        appSitePlace.setType(SitePlaceTypeEnum.UNFIXED.getCode());
        appSitePlace.setOrgCode(site.getOrgCode());
        appSitePlace.setTenantId(site.getTenantId());
        int updateById = baseMapper.updateById(appSitePlace);
        if (updateById < 1) throw new JeecgBootException("无固定场编辑失败", SC_INTERNAL_SERVER_ERROR_500);
        //查询无固定场价格表对应数据，查询对应数据修改
        List<AppSitePriceRules> appSitePriceRulesList = appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, unsetDTO.getId()));
        String[] split = unsetDTO.getDownTime().split(",");
        List<String> downTimes = Arrays.stream(split).collect(Collectors.toList());
        appSitePriceRulesList.forEach(appSitePriceRules -> {
            appSitePriceRules
                    .setSitePlaceId(appSitePlace.getId())
                    .setOrgCode(appSitePlace.getOrgCode())
                    .setTenantId(appSitePlace.getTenantId())
                    .setType(SitePlaceTypeEnum.UNFIXED.getCode())
                    .setOriginalPrice(unsetDTO.getOriginalPrice())
                    .setSellingPrice(unsetDTO.getSellingPrice())
            ;
            if (downTimes.contains(appSitePriceRules.getDayOfWeek())) {
                appSitePriceRules.setStatus(1);
            }
            appSitePriceRulesMapper.updateById(appSitePriceRules);
        });
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteUnfixed(String id) {
        AppSitePlace dbPlace = baseMapper.selectById(id);
        if (null == dbPlace) throw new JeecgBootException("未找到对应数据", SC_INTERNAL_SERVER_ERROR_500);
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        dbPlace.setUpdateBy(sysUser.getUsername());
        int deleteById = baseMapper.deleteById(dbPlace);
        if (deleteById < 1) throw new JeecgBootException("无固定场删除失败", SC_INTERNAL_SERVER_ERROR_500);
        int deleteById1 = appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, id));
        if (deleteById1 < 1) throw new JeecgBootException("固定场价格规则删除失败", SC_INTERNAL_SERVER_ERROR_500);
        return Boolean.TRUE;
    }

    @Override
    public IPage<AppSitePlaceUnfixedDTO> queryUnfixedPage(AppSitePlaceUnfixedPageDTO dto) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Page<AppSitePlace> page = new Page<>(dto.getPageNo(), dto.getPageSize());
        LambdaQueryWrapper<AppSitePlace> wrapper = Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getType, SitePlaceTypeEnum.UNFIXED.getCode())
                .likeRight(AppSitePlace::getOrgCode, loginUser.getOrgCode())
                .eq(AppSitePlace::getType, SitePlaceTypeEnum.UNFIXED.getCode())
                .like(StringUtils.isNotBlank(dto.getName()), AppSitePlace::getName, dto.getName()).orderByDesc(AppSitePlace::getCreateTime);
        if(null != dto.getSiteId() && !"ALL".equals(dto.getSiteId())){
            wrapper.eq(AppSitePlace::getSiteId, dto.getSiteId());
        }
        IPage<AppSitePlace> resultPage = baseMapper.selectPage(page, wrapper);
        return resultPage.convert(record -> {
            AppSitePlaceUnfixedDTO appSitePlaceUnfixedDTO = new AppSitePlaceUnfixedDTO();
            BeanUtils.copyProperties(record, appSitePlaceUnfixedDTO);
            appSitePlaceUnfixedDTO.setVenuesName(appSiteMapper.selectById(record.getSiteId()).getName());
            List<AppSitePriceRules> appSitePriceRulesList = appSitePriceRulesMapper.selectList(
                    Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, record.getId()).eq(AppSitePriceRules::getStatus, CommonConstant.STATUS_0_INT));
            if (CollUtil.isNotEmpty(appSitePriceRulesList)) {
                appSitePlaceUnfixedDTO.setOriginalPrice(appSitePriceRulesList.get(0).getOriginalPrice());
                appSitePlaceUnfixedDTO.setSellingPrice(appSitePriceRulesList.get(0).getSellingPrice());
            }
            return appSitePlaceUnfixedDTO;
        });
    }

    @Override
    public AppSitePlaceUnfixedDTO queryUnfixedById(String id) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        AppSitePlace dbSitePlace = baseMapper.selectById(id);
        if (null == dbSitePlace) throw new JeecgBootException("无固定场数据不存在", SC_INTERNAL_SERVER_ERROR_500);
        AppSitePriceRules appSitePriceRules = appSitePriceRulesMapper.selectOne(
                Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, dbSitePlace.getId()));
        AppSitePlaceUnfixedDTO appSitePlaceUnfixedDTO = new AppSitePlaceUnfixedDTO();
        BeanUtils.copyProperties(dbSitePlace, appSitePlaceUnfixedDTO);
        appSitePlaceUnfixedDTO.setOriginalPrice(appSitePriceRules.getOriginalPrice());
        appSitePlaceUnfixedDTO.setSellingPrice(appSitePriceRules.getSellingPrice());

        return appSitePlaceUnfixedDTO;
    }

    //包场
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public Boolean savePack(AppSitePlaceDTO placeDTO) {
//        AppSitePlaceCuDTO placeCuDTO = placeDTO.getAppSitePlaceCuDTO();
//        List<AppSiteRuleDTO> siteRuleDTOS = placeDTO.getSiteRuleDTOS();
//        AppSite site = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getTenantId,placeCuDTO.getSiteId()));

    /// /        AppSite site = appSiteMapper.selectById(placeCuDTO.getSiteId());
//        placeDTO.getSiteCategoryDOTS().forEach(item -> {
//            AppCategory category = appCategoryMapper.selectById(item.getCategoryId());
//            for (int i = 0; i < item.getCount(); i++) {
//                AppSitePlace appSitePlace = new AppSitePlace();
//                BeanUtils.copyProperties(placeCuDTO, appSitePlace);
//                appSitePlace.setType(SitePlaceTypeEnum.PACKAGE.getCode());
//                appSitePlace.setName(category.getName() + (i + 1));
//                appSitePlace.setSiteId(site.getId());
//                appSitePlace.setOrgCode(site.getOrgCode());
//                appSitePlace.setTenantId(site.getTenantId());
//                appSitePlace.setCategoryId(category.getId());
//                int insert = baseMapper.insert(appSitePlace);
//                if (insert < 1) throw new JeecgBootException("包场保存失败", SC_INTERNAL_SERVER_ERROR_500);
//                siteRuleDTOS.stream().filter(rule -> rule.getCategoryId().equals(category.getId())).collect(Collectors.toList()).forEach(rule -> {
//                    AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
//                    BeanUtils.copyProperties(rule, appSitePriceRules);
//                    appSitePriceRules.setSitePlaceId(appSitePlace.getId());
//                    appSitePriceRules.setOrgCode(appSitePlace.getOrgCode());
//                    appSitePriceRules.setTenantId(appSitePlace.getTenantId());
//
//                    String batchUUID = IdUtil.simpleUUID();
//                    appSitePriceRules.setBatchuuid(batchUUID);
//                    int savePriceResult = appSitePriceRulesMapper.insert(appSitePriceRules);
//                    if (savePriceResult < 1)
//                        throw new JeecgBootException("包场价格保存失败", SC_INTERNAL_SERVER_ERROR_500);
//                });
//            }
//        });
//        return Boolean.TRUE;
//    }

    //包场新增
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean savePack(AppSitePlaceParkDTO appSitePlaceParkDTO) {
        AppSitePlaceCuDTO placeCuDTO = appSitePlaceParkDTO.getAppSitePlaceCuDTO();
        List<AppSiteCategoryRuleDTO> appSiteCategoryRuleDTOS = appSitePlaceParkDTO.getAppSiteCategoryRuleDTOS();
        AppSite site = appSiteMapper.selectById(placeCuDTO.getSiteId());
        appSiteCategoryRuleDTOS.forEach(item -> {
            AppCategory category = appCategoryMapper.selectById(item.getCategoryId());

            List<AppSiteRuleTimeFormDTO> appSiteRuleTimeFormDTOList = item.getAppSiteRuleTimeFormDTOList();
            for (AppSiteRuleTimeFormDTO appSiteRuleTimeFormDTO : appSiteRuleTimeFormDTOList) {
                AppSiteRuleTime appSiteRuleTime = new AppSiteRuleTime();
                appSiteRuleTime.setSiteId(site.getId());
                appSiteRuleTime.setCategoryId(category.getId());
                appSiteRuleTime.setStartTime(appSiteRuleTimeFormDTO.getStartTime());
                appSiteRuleTime.setEndTime(appSiteRuleTimeFormDTO.getEndTime());
                appSiteRuleTimeMapper.insert(appSiteRuleTime);
                List<AppSiteRuleDTO> appSiteRuleDTOList = appSiteRuleTimeFormDTO.getAppSiteRuleDTOList();
                for (AppSiteRuleDTO appSiteRuleDTO : appSiteRuleDTOList) {
                    appSiteRuleDTO.setSiteRuleTimeId(appSiteRuleTime.getId());
                }
            }

            for (int i = 0; i < item.getCount(); i++) {
                AppSitePlace appSitePlace = new AppSitePlace();
                BeanUtils.copyProperties(placeCuDTO, appSitePlace);
                appSitePlace.setType(SitePlaceTypeEnum.PACKAGE.getCode());
                appSitePlace.setName(category.getName() + (i + 1));
                appSitePlace.setSiteId(site.getId());
                appSitePlace.setOrgCode(site.getOrgCode());
                appSitePlace.setTenantId(site.getTenantId());
                appSitePlace.setCategoryId(category.getId());
                appSitePlace.setType(SitePlaceTypeEnum.PACKAGE.getCode());
                appSitePlace.setRefundType(placeCuDTO.getRefundType());
                appSitePlace.setEarlyRefundTime(placeCuDTO.getEarlyRefundTime());
                appSitePlace.setReminder(placeCuDTO.getReminder());
                int insert = baseMapper.insert(appSitePlace);
                if (insert < 1) throw new JeecgBootException("包场保存失败", SC_INTERNAL_SERVER_ERROR_500);

                List<AppSitePriceRules> appSitePriceRulesList = new ArrayList<>();

                item.getAppSiteRuleTimeFormDTOList().forEach(formDTO -> {
                    formDTO.getAppSiteRuleDTOList().forEach(ruleDTO -> {
                        AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
                        BeanUtils.copyProperties(formDTO, appSitePriceRules);
                        appSitePriceRules.setSitePlaceId(appSitePlace.getId());
                        appSitePriceRules.setOrgCode(appSitePlace.getOrgCode());
                        appSitePriceRules.setTenantId(appSitePlace.getTenantId());
                        appSitePriceRules.setCategoryId(category.getId());
                        appSitePriceRules.setDayOfWeek(ruleDTO.getDayOfWeek());
                        appSitePriceRules.setSellingPrice(ruleDTO.getSellingPrice());
                        appSitePriceRules.setType(appSitePlace.getType());
                        appSitePriceRules.setSiteRuleTimeId(ruleDTO.getSiteRuleTimeId());
                        appSitePriceRules.setStatus(CommonConstant.STATUS_0_INT);
                        appSitePriceRules.setDelFlag(CommonConstant.STATUS_0_INT);
                        appSitePriceRulesList.add(appSitePriceRules);
                    });
                });
                appSitePriceRulesMapper.insertList(appSitePriceRulesList);
            }
        });

        return Boolean.TRUE;
    }

    /**
     * 包场修改
     *
     * @param appSitePlaceParkDTO
     * @return Boolean
     */
//    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editPack1(AppSitePlaceParkDTO appSitePlaceParkDTO) {
        AppSitePlaceCuDTO placeCuDTO = appSitePlaceParkDTO.getAppSitePlaceCuDTO();
        List<AppSiteCategoryRuleDTO> appSiteCategoryRuleDTOS = appSitePlaceParkDTO.getAppSiteCategoryRuleDTOS();
        AppSite site = appSiteMapper.selectById(placeCuDTO.getSiteId());
        if (site == null) {
            throw new JeecgBootException("商户门店不存在", SC_INTERNAL_SERVER_ERROR_500);
        }
        // 查询当前场地的所有包场场所
        List<AppSitePlace> existingPlaces = baseMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery()
                .eq(AppSitePlace::getSiteId, site.getId())
                .eq(AppSitePlace::getType, SitePlaceTypeEnum.PACKAGE.getCode()));
        if (existingPlaces.isEmpty()) {
            // 无须对比直接做新增
            return savePack(appSitePlaceParkDTO);
        }
        // 对比修改
        for (AppSiteCategoryRuleDTO appSiteCategoryRuleDTO : appSiteCategoryRuleDTOS) {
            // 收集所有新的分类ID
            Set<String> newCategoryIds = appSiteCategoryRuleDTOS.stream()
                    .map(AppSiteCategoryRuleDTO::getCategoryId)
                    .collect(Collectors.toSet());

            // 删除不在新分类列表中的现有场地
            existingPlaces.forEach(place -> {
                if (!newCategoryIds.contains(place.getCategoryId())) {
                    baseMapper.deleteById(place);
                }
            });

            String categoryId = appSiteCategoryRuleDTO.getCategoryId();
            Integer count = appSiteCategoryRuleDTO.getCount();

            // 查询该分类已有的场地
            List<AppSitePlace> sitePlaces = existingPlaces.stream().filter(p -> p.getCategoryId() != null && p.getCategoryId().equals(categoryId)).collect(Collectors.toList());

            AppCategory category = appCategoryMapper.selectById(categoryId);
            if (category == null) {
                throw new JeecgBootException("分类不存在", SC_INTERNAL_SERVER_ERROR_500);
            }

            if (sitePlaces.isEmpty()) {
                // 创建场地
                for (int i = 1; i <= count; i++) {
                    AppSitePlace appSitePlace = new AppSitePlace();
                    BeanUtils.copyProperties(placeCuDTO, appSitePlace);
                    appSitePlace.setType(SitePlaceTypeEnum.PACKAGE.getCode());
                    appSitePlace.setName(category.getName() + i);
                    appSitePlace.setSiteId(site.getId());
                    appSitePlace.setOrgCode(site.getOrgCode());
                    appSitePlace.setTenantId(site.getTenantId());
                    appSitePlace.setCategoryId(category.getId());
                    appSitePlace.setType(SitePlaceTypeEnum.PACKAGE.getCode());
                    baseMapper.insert(appSitePlace);
                }
                sitePlaces = baseMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getSiteId, site.getId()).eq(AppSitePlace::getCategoryId, category.getId()));
            }

            // 表单siteRuleTimeId集合
            List<String> formIds = appSiteCategoryRuleDTO.getAppSiteRuleTimeFormDTOList().stream().map(AppSiteRuleTimeFormDTO::getId).filter(StrUtil::isNotBlank).collect(Collectors.toList());

            // 查询本地所有的siteRuleTime
            List<AppSiteRuleTime> appSiteRuleTimeList = appSiteRuleTimeMapper.selectList(Wrappers.<AppSiteRuleTime>lambdaQuery().eq(AppSiteRuleTime::getSiteId, site.getId()).eq(AppSiteRuleTime::getCategoryId, categoryId));
            // 删除
            if (CollUtil.isNotEmpty(appSiteRuleTimeList)) {
                List<String> localIds = appSiteRuleTimeList.stream().map(AppSiteRuleTime::getId).collect(Collectors.toList());
                // 找出要删除的旧规则（存在于db，不存在于new）
                List<String> toDelete = getDifferListByMap(localIds, formIds);

                if (!toDelete.isEmpty()) {
                    toDelete.forEach(id -> {
                        appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSiteRuleTimeId, id));
                    });
                    appSiteRuleTimeMapper.deleteBatchIds(toDelete);
                }
            }

            List<AppSiteRuleTimeFormDTO> appSiteRuleTimeFormDTOList = appSiteCategoryRuleDTO.getAppSiteRuleTimeFormDTOList();
            for (AppSiteRuleTimeFormDTO formDTO : appSiteRuleTimeFormDTOList) {

                // 新增
                if (StrUtil.isBlank(formDTO.getId())) {
                    AppSiteRuleTime appSiteRuleTime = new AppSiteRuleTime();
                    appSiteRuleTime.setSiteId(site.getId()).setCategoryId(category.getId()).setStartTime(formDTO.getStartTime()).setEndTime(formDTO.getEndTime());
                    appSiteRuleTimeMapper.insert(appSiteRuleTime);
                    formDTO.getAppSiteRuleDTOList().forEach(ruleDTO -> {
                        ruleDTO.setSiteRuleTimeId(appSiteRuleTime.getId());
                    });

                    if (CollUtil.isNotEmpty(sitePlaces)) {
                        List<AppSitePriceRules> appSitePriceRulesList = new ArrayList<>();

                        for (AppSitePlace sitePlace : sitePlaces) {
                            for (AppSiteRuleDTO ruleDTO : formDTO.getAppSiteRuleDTOList()) {
                                AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
                                BeanUtils.copyProperties(formDTO, appSitePriceRules);
                                appSitePriceRules.setId(null);
                                appSitePriceRules.setSitePlaceId(sitePlace.getId());
                                appSitePriceRules.setOrgCode(sitePlace.getOrgCode());
                                appSitePriceRules.setTenantId(sitePlace.getTenantId());
                                appSitePriceRules.setCategoryId(category.getId());
                                appSitePriceRules.setDayOfWeek(ruleDTO.getDayOfWeek());
                                appSitePriceRules.setSellingPrice(ruleDTO.getSellingPrice());
                                appSitePriceRules.setType(sitePlace.getType());
                                appSitePriceRules.setSiteRuleTimeId(ruleDTO.getSiteRuleTimeId());
                                appSitePriceRules.setStatus(CommonConstant.STATUS_0_INT);
                                appSitePriceRules.setDelFlag(CommonConstant.STATUS_0_INT);
                                appSitePriceRulesList.add(appSitePriceRules);
                            }
                        }
                        for (AppSitePriceRules appSitePriceRules : appSitePriceRulesList) {
                            appSitePriceRulesMapper.insert(appSitePriceRules);
                        }
                    }
                }
                // 修改
                else {
                    AppSiteRuleTime appSiteRuleTime = appSiteRuleTimeMapper.selectById(formDTO.getId());
                    appSiteRuleTime.setSiteId(site.getId()).setCategoryId(category.getId()).setStartTime(formDTO.getStartTime()).setEndTime(formDTO.getEndTime());
                    appSiteRuleTimeMapper.updateById(appSiteRuleTime);
                    List<AppSitePriceRules> appSitePriceRules = appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSiteRuleTimeId, appSiteRuleTime.getId()));
                    List<AppSiteRuleDTO> appSiteRuleDTOList = formDTO.getAppSiteRuleDTOList();
                    for (AppSiteRuleDTO appSiteRuleDTO : appSiteRuleDTOList) {
                        for (AppSitePriceRules appSitePriceRule : appSitePriceRules) {
                            if (Objects.equals(appSitePriceRule.getDayOfWeek(), appSiteRuleDTO.getDayOfWeek())) {
                                appSitePriceRule.setStartTime(appSiteRuleDTO.getStartTime()).setEndTime(appSiteRuleDTO.getEndTime()).setSellingPrice(appSiteRuleDTO.getSellingPrice());
                            }
                        }
                    }
                    for (AppSitePriceRules appSitePriceRule : appSitePriceRules) {
                        appSitePriceRulesMapper.updateById(appSitePriceRule);
                    }
                }
            }
            Long sitePlaceNum = baseMapper.selectCount(Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getSiteId, site.getId()).eq(AppSitePlace::getCategoryId, categoryId));
            // 数据库场地数量    小于   表单场地数量  -----新增多余场地数量
            if (sitePlaceNum < count) {
                if (sitePlaceNum > 0) {
                    // 增加场地 数量
                    for (int i = 1; i <= count - sitePlaceNum; i++) {
                        AppSitePlace appSitePlace = new AppSitePlace();
                        BeanUtils.copyProperties(placeCuDTO, appSitePlace);
                        appSitePlace.setSiteId(site.getId()).setCategoryId(categoryId).setName(category.getName() + (sitePlaceNum + i)).setType(SitePlaceTypeEnum.PACKAGE.getCode()).setOrgCode(site.getOrgCode()).setTenantId(site.getTenantId());
                        baseMapper.insert(appSitePlace);
                        List<AppSitePriceRules> appSitePriceRulesList = new ArrayList<>();
                        appSiteCategoryRuleDTO.getAppSiteRuleTimeFormDTOList().forEach(formDTO -> {
                            List<AppSiteRuleDTO> appSiteRuleDTOList = formDTO.getAppSiteRuleDTOList();
                            for (AppSiteRuleDTO appSiteRuleDTO : appSiteRuleDTOList) {
                                AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
                                BeanUtils.copyProperties(appSiteRuleDTO, appSitePriceRules);
                                appSitePriceRulesList.add(appSitePriceRules);
                            }
                        });
                        appSitePriceRulesMapper.insertList(appSitePriceRulesList);
                    }
                }
            }
            // 数据库场地数量    大于   表单场地数量  -----删除多余场地数量
            if (sitePlaceNum > count) {
                // 减少场地 数量
                for (int i = 0; i < sitePlaceNum - count; i++) {
                    // 名称匹配
                    AppSitePlace appSitePlace = baseMapper.selectOne(Wrappers.<AppSitePlace>lambdaQuery()
                            .eq(AppSitePlace::getSiteId, site.getId())
                            .eq(AppSitePlace::getCategoryId, categoryId)
                            .eq(AppSitePlace::getName, category.getName() + (sitePlaceNum - i)));
                    log.debug(appSitePlace.getName());
                    if (ObjectUtil.isNotEmpty(appSitePlace)) {
                        appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId()));
                        baseMapper.deleteById(appSitePlace);
                    }
                }
            }
        }
        return Boolean.TRUE;
    }

    public static List<String> getDifferListByMap(List<String> listA, List<String> listB) {
        List<String> differList = new ArrayList<>();
        Map<String, Integer> map = new HashMap<>();
        for (String strA : listA) {
            map.put(strA, 1);
        }
        for (String strB : listB) {
            Integer value = map.get(strB);
            if (value != null) {
                map.put(strB, ++value);
                continue;
            }
            map.put(strB, 1);
        }
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            if (entry.getValue() == 1) {
                differList.add(entry.getKey());
            }
        }
        return differList;
    }

    @Override
    public AppSitePlaceDTO queryPackById(String id) {
        AppSitePlace dbPlace = baseMapper.selectById(id);
        if (null == dbPlace) throw new JeecgBootException("包场数据不存在", SC_INTERNAL_SERVER_ERROR_500);
        AppSitePlaceCuDTO placeCuDTO = new AppSitePlaceCuDTO();
        BeanUtils.copyProperties(dbPlace, placeCuDTO);
        List<AppSiteRuleDTO> collect = appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, id)).stream().map(rule -> {
            AppSiteRuleDTO appSiteRuleDTO = new AppSiteRuleDTO();
            BeanUtils.copyProperties(rule, appSiteRuleDTO);
            return appSiteRuleDTO;
        }).collect(Collectors.toList());
        Map<String, List<AppSiteRuleDTO>> collect1 = collect.stream().collect(Collectors.groupingBy(AppSiteRuleDTO::getCategoryId));
        List<AppSiteCategoryDOT> appSiteCategoryDOTs = collect1.entrySet().stream().map(entry -> {
            AppSiteCategoryDOT appSiteCategoryDOT = new AppSiteCategoryDOT();
            appSiteCategoryDOT.setCategoryId(entry.getKey());
            appSiteCategoryDOT.setCount(entry.getValue().size());
            return appSiteCategoryDOT;
        }).collect(Collectors.toList());

        return new AppSitePlaceDTO(placeCuDTO, collect, appSiteCategoryDOTs);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletePackById(String id) {
        AppSitePlace dbPlace = baseMapper.selectById(id);
        if (null == dbPlace) throw new JeecgBootException("包场数据不存在", SC_INTERNAL_SERVER_ERROR_500);
        List<AppSitePlace> appSitePlaces = baseMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getSiteId, id));
        appSitePlaces.forEach(appSitePlace -> {
            int deleteResult = baseMapper.deleteById(appSitePlace.getId());
            if (deleteResult < 1) {
                throw new JeecgBootException("包场数据删除失败", SC_INTERNAL_SERVER_ERROR_500);
            }
            int delete = appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId()));
            if (delete < 1) {
                throw new JeecgBootException("包场价格规则删除失败", SC_INTERNAL_SERVER_ERROR_500);
            }
        });

        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addSchoolPlace(SchoolPlaceAddDTO schoolPlaceAddDTO) {

        //部门ID查询学校场地
        AppSite site = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getTenantId, schoolPlaceAddDTO.getTenantId()).last("limit 1"));

        //根据学校查询场地
        AppSitePlace appSitePlace = baseMapper.selectOne(Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getTenantId, site.getTenantId()));

        //判断当前教学日配置是否与原数据对应
        if (ObjectUtils.notEqual(site.getTeachingDay(), schoolPlaceAddDTO.getTeachingDay()) || ObjectUtils.notEqual(site.getNoTeachingDay(), schoolPlaceAddDTO.getNoTeachingDay())) {

            site.setTeachingDay(schoolPlaceAddDTO.getTeachingDay());
            site.setNoTeachingDay(schoolPlaceAddDTO.getNoTeachingDay());

            int year = DateUtils.getYear();

//            Map<String, List<String>> HolidayMap = HolidayUtil.getYearHoliday(String.valueOf(year));

            //当前日期
//            Date currDate = DateUtils.str2Date(DateUtils.now(), new SimpleDateFormat("yyyy-MM-dd"));

            // 创建一个Calendar实例
            Calendar calendar = Calendar.getInstance();

            // 获取当前日期
            Date currentDate = new Date();
            calendar.setTime(currentDate);

            // 将日期向前推一天
            calendar.add(Calendar.DAY_OF_MONTH, -1);

            // 获取前一天的日期
            Date previousDate = calendar.getTime();


            // 设置开始日期和结束日期
            Date beginDate = DateUtils.str2Date((year) + "-01-01 00:00:00", new SimpleDateFormat("yyyy-MM-dd"));
            Date endDate = DateUtils.str2Date((year + 1) + "-01-01 00:00:00", new SimpleDateFormat("yyyy-MM-dd"));

            // 获取开始日期和结束日期之间的所有日期
            List<Date> dateList = HolidayUtil.getDaysBetweenDates(beginDate, endDate);
            //当前日期之后的数据
            List<Date> dates = dateList.stream().filter(date -> date.after(previousDate)).collect(Collectors.toList());

            //部门、场地、教学日（teaching）、
            List<AppSitePriceRules> appSitePriceRulesList = new ArrayList<>();

            // 遍历生成一对多教学时段
            for (Date localDate : dates) {
                //查询
                AppTeachingTime appTeachingTime = appTeachingTimeMapper.selectOne(Wrappers.<AppTeachingTime>lambdaQuery()
                        .eq(AppTeachingTime::getTenantId, site.getTenantId()).eq(AppTeachingTime::getDay, localDate));

                //如果开放时段列表不为空(教学日/非教学日)，根据开放时段批量存储，开放时段记录
                if (ObjectUtils.isNotEmpty(site.getTeachingDay()) && appTeachingTime.getIsTeaching() == 0) {

                    //解析Json 数据
                    List<TeachingDayDTO> data = JSONObject.parseObject(site.getTeachingDay()).getJSONArray("data").toJavaList(TeachingDayDTO.class);
                    data.forEach(item -> {

                        String startTime = item.getStartTime();
                        String endTime = item.getEndTime();
                        Integer ticketNum = Integer.valueOf(item.getTicketNum());

                        AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
                        appSitePriceRules
                                .setOrgCode(site.getOrgCode())
                                .setTenantId(site.getTenantId())
                                .setSitePlaceId(appSitePlace.getId())
                                .setType(0)
                                .setTicketNum(ticketNum)
                                .setDateOfSale(localDate)
                                .setStartTime(DateUtils.str2Date(startTime, new SimpleDateFormat("HH:mm")))
                                .setEndTime(DateUtils.str2Date(endTime, new SimpleDateFormat("HH:mm")))
                                .setDayOfWeek(HolidayUtil.getWeekOfDate(localDate))
                                .setIsTeaching(appTeachingTime.getIsTeaching())
                                .setCategoryId(site.getCategoryId())
                                .setCreateBy("admin")
                                .setCreateTime(new Date())
                                .setStatus(CommonConstant.STATUS_NORMAL)
                                .setDelFlag(CommonConstant.STATUS_NORMAL)
                        ;
                        appSitePriceRulesList.add(appSitePriceRules);
                    });

                }
                if (ObjectUtils.isNotEmpty(site.getNoTeachingDay()) && appTeachingTime.getIsTeaching() == 1) {

                    List<TeachingDayDTO> data = JSONObject.parseObject(site.getNoTeachingDay()).getJSONArray("data").toJavaList(TeachingDayDTO.class);
                    data.forEach(item -> {

                        String startTime = item.getStartTime();
                        String endTime = item.getEndTime();
                        Integer ticketNum = Integer.valueOf(item.getTicketNum());

                        AppSitePriceRules appSitePriceRules = new AppSitePriceRules();
                        appSitePriceRules
                                .setOrgCode(site.getOrgCode())
                                .setTenantId(site.getTenantId())
                                .setSitePlaceId(appSitePlace.getId())
                                .setType(0)
                                .setTicketNum(ticketNum)
                                .setDateOfSale(localDate)
                                .setStartTime(DateUtils.str2Date(startTime, new SimpleDateFormat("HH:mm")))
                                .setEndTime(DateUtils.str2Date(endTime, new SimpleDateFormat("HH:mm")))
                                .setDayOfWeek(HolidayUtil.getWeekOfDate(localDate))
                                .setIsTeaching(appTeachingTime.getIsTeaching())
                                .setCategoryId(site.getCategoryId())
                                .setCreateBy("admin")
                                .setCreateTime(new Date())
                                .setStatus(CommonConstant.STATUS_NORMAL)
                                .setDelFlag(CommonConstant.STATUS_NORMAL)
                        ;
                        appSitePriceRulesList.add(appSitePriceRules);
                    });
                }
            }
            //存放开放时段列表(删除再新增)
            appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().gt(AppSitePriceRules::getDateOfSale, previousDate).eq(AppSitePriceRules::getOrgCode, site.getOrgCode()));
            appSitePriceRulesMapper.insertList(appSitePriceRulesList);

            appSiteMapper.updateById(site);
        }
        //修改学校场地开放信息
        appSitePlace
                .setCover(schoolPlaceAddDTO.getCover().split( ",")[0])
                // 设置意外保险字段
                .setInsureIds(schoolPlaceAddDTO.getInsureIds())
                .setReminder(schoolPlaceAddDTO.getReminder());
        return this.updateById(appSitePlace);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SchoolPlaceAddDTO querySchoolPlace(String orgCode) {

        SchoolPlaceAddDTO schoolPlaceAddDTO = new SchoolPlaceAddDTO();

        AppSite site = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getOrgCode, orgCode));

        if (ObjectUtils.isEmpty(site)) {
            return null;
        }

        AppSitePlace appSitePlace = this.baseMapper.selectOne(Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getOrgCode, orgCode));

        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        schoolPlaceAddDTO
                .setTenantId(site.getTenantId())
                .setTeachingDay(site.getTeachingDay())
                .setNoTeachingDay(site.getNoTeachingDay())
        ;

        if (ObjectUtils.isNotEmpty(appSitePlace)) {
            schoolPlaceAddDTO
                    .setSiteId(site.getId())
                    .setSiteId(appSitePlace.getId())
                    .setPlaceId(appSitePlace.getId())
                    .setInsureIds(appSitePlace.getInsureIds())
                    .setReminder(appSitePlace.getReminder());
            if (ObjectUtil.isNotEmpty(appSitePlace.getCover())) {
                schoolPlaceAddDTO.setCover(appSitePlace.getCover().split( ",")[0]);
            }
        }

        if ("admin".equals(loginUser.getRoleCode())) {
            schoolPlaceAddDTO.setHavePermission(Boolean.TRUE);
        }

        return schoolPlaceAddDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppSitePlaceParkDTO queryPack(String siteId) {
        AppSitePlaceParkDTO appSitePlaceParkDTO = new AppSitePlaceParkDTO();
        AppSite site = appSiteMapper.selectById(siteId);
        List<AppSitePlace> appSitePlaceList = this.baseMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery()
                .eq(AppSitePlace::getSiteId, site.getId())
                .eq(AppSitePlace::getType, SitePlaceTypeEnum.PACKAGE.getCode()));
        if (ObjectUtils.isNotEmpty(appSitePlaceList)) {
            List<AppSiteCategoryRuleDTO> appSiteCategoryRuleDTOS = new ArrayList<>();
            if (CollUtil.isNotEmpty(appSitePlaceList)) {
                AppSitePlace appSitePlace = appSitePlaceList.get(0);
                AppSitePlaceCuDTO placeCuDTO = new AppSitePlaceCuDTO();
                BeanUtils.copyProperties(appSitePlace, placeCuDTO);
                appSitePlaceParkDTO.setAppSitePlaceCuDTO(placeCuDTO);

                Map<String, List<AppSitePlace>> map = appSitePlaceList.stream().collect(Collectors.groupingBy(AppSitePlace::getCategoryId));
                for (String key : map.keySet()) {
                    List<AppSitePlace> placeList = map.get(key);
                    AppSiteCategoryRuleDTO appSiteCategoryRuleDTO = new AppSiteCategoryRuleDTO();
                    appSiteCategoryRuleDTO.setCategoryId(key);
                    appSiteCategoryRuleDTO.setCount(placeList.size());
                    // 查询当前场地的规则时间列表
                    List<AppSiteRuleTime> appSiteRuleTimeList = appSiteRuleTimeMapper.selectList(Wrappers.<AppSiteRuleTime>lambdaQuery().eq(AppSiteRuleTime::getSiteId, site.getId()).eq(AppSiteRuleTime::getCategoryId, key));
                    List<AppSiteRuleTimeFormDTO> formDTOList = new ArrayList<>();
                    if (ObjectUtils.isNotEmpty(appSiteRuleTimeList)) {
                        for (AppSiteRuleTime appSiteRuleTime : appSiteRuleTimeList) {
                            AppSiteRuleTimeFormDTO appSiteRuleTimeFormDTO = new AppSiteRuleTimeFormDTO();

                            appSiteRuleTimeFormDTO.setId(appSiteRuleTime.getId());
                            appSiteRuleTimeFormDTO.setStartTime(appSiteRuleTime.getStartTime());
                            appSiteRuleTimeFormDTO.setEndTime(appSiteRuleTime.getEndTime());

                            List<AppSiteRuleDTO> appSiteRuleDTOS = new ArrayList<>();

                            // 去重，根据星期，只取一条
                            List<AppSitePriceRules> appSitePriceRulesList = appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSiteRuleTimeId, appSiteRuleTime.getId())
//                                    .eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId())
                            );
                            List<AppSitePriceRules> weekList = new ArrayList<>();
                            Map<String, List<AppSitePriceRules>> siteRuleMap = appSitePriceRulesList.stream().collect(Collectors.groupingBy(AppSitePriceRules::getDayOfWeek));
                            for (String week : siteRuleMap.keySet()) {
                                // 每个week取第一条(共7条)
                                List<AppSitePriceRules> appSitePriceRules = siteRuleMap.get(week);
                                if (ObjectUtils.isNotEmpty(appSitePriceRules)) {
                                    weekList.add(appSitePriceRules.get(0));
                                }
                            }
                            if (ObjectUtils.isNotEmpty(weekList)) {
                                for (AppSitePriceRules appSitePriceRules : weekList) {
                                    AppSiteRuleDTO appSiteRuleDTO = new AppSiteRuleDTO();
                                    BeanUtils.copyProperties(appSitePriceRules, appSiteRuleDTO);
                                    appSiteRuleDTOS.add(appSiteRuleDTO);
                                }
                                appSiteRuleTimeFormDTO.setAppSiteRuleDTOList(appSiteRuleDTOS);
                            }
                            appSiteRuleTimeFormDTO.setAppSiteRuleDTOList(appSiteRuleDTOS);
                            formDTOList.add(appSiteRuleTimeFormDTO);
                        }
                        appSiteCategoryRuleDTO.setAppSiteRuleTimeFormDTOList(formDTOList);
                    }
                    appSiteCategoryRuleDTOS.add(appSiteCategoryRuleDTO);
                }
                appSitePlaceParkDTO.setAppSiteCategoryRuleDTOS(appSiteCategoryRuleDTOS);
            }
            return appSitePlaceParkDTO;
        }
        return null;
    }

    @Override
    public List<AppSite> queryByOrgCode(QueryByOrgCodeForm queryByOrgCodeForm) {
        return appSiteMapper.selectList(Wrappers.<AppSite>lambdaQuery()
                        .eq(ObjectUtil.isNotEmpty(queryByOrgCodeForm.getType()), AppSite::getType, queryByOrgCodeForm.getType())
                .likeRight(AppSite::getOrgCode, queryByOrgCodeForm.getOrgCode())
                .eq(AppSite::getDelFlag, 0));
    }

    /**
     * 权限校验
     *
     * @param place
     * @param sysUser
     */
    private void checkPermission(AppSitePlace place, LoginUser sysUser) {
        if (!sysUser.getOrgCode().equals(place.getOrgCode()))
            throw new JeecgBootException("无权限操作", SC_INTERNAL_SERVER_ERROR_500);
    }


    /**
     * 包场修改
     *
     * @param appSitePlaceParkDTO
     * @return Boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editPack(AppSitePlaceParkDTO appSitePlaceParkDTO) {
        if (appSitePlaceParkDTO == null || appSitePlaceParkDTO.getAppSitePlaceCuDTO() == null) {
            throw new JeecgBootException("参数不能为空", SC_INTERNAL_SERVER_ERROR_500);
        }

        AppSitePlaceCuDTO placeCuDTO = appSitePlaceParkDTO.getAppSitePlaceCuDTO();

        List<AppSiteCategoryRuleDTO> appSiteCategoryRuleDTOS = appSitePlaceParkDTO.getAppSiteCategoryRuleDTOS();

        if (CollUtil.isEmpty(appSiteCategoryRuleDTOS)) {
            return true; // 无配置则无需处理
        }

        AppSite site = appSiteMapper.selectById(placeCuDTO.getSiteId());
        if (site == null) {
            throw new JeecgBootException("商户门店不存在", SC_INTERNAL_SERVER_ERROR_500);
        }

        // 查询当前场地的所有包场场所
        List<AppSitePlace> existingPlaces = baseMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery()
                .eq(AppSitePlace::getSiteId, site.getId())
                .eq(AppSitePlace::getType, SitePlaceTypeEnum.PACKAGE.getCode()));

        if (existingPlaces.isEmpty()) {
            // 无须对比直接做新增
            return savePack(appSitePlaceParkDTO);
        }

        //修改所有的sitePlace的退款，预定限制，温馨提示
        for (AppSitePlace existingPlace : existingPlaces) {
            if (!ObjectUtil.equals(existingPlace.getEarlyRefundTime(), placeCuDTO.getEarlyRefundTime()) ||
                    !ObjectUtil.equals(existingPlace.getBuyLimit(), placeCuDTO.getBuyLimit()) ||
                    !ObjectUtil.equals(existingPlace.getReminder(), placeCuDTO.getReminder()) ||
                    !ObjectUtil.equals(existingPlace.getRefundType(), placeCuDTO.getRefundType())
            ) {
                if (!ObjectUtil.equals(existingPlace.getRefundType(), placeCuDTO.getRefundType())) {
                    existingPlace.setRefundType(placeCuDTO.getRefundType());
                }
                if (!ObjectUtil.equals(existingPlace.getEarlyRefundTime(), placeCuDTO.getEarlyRefundTime())) {
                    existingPlace.setEarlyRefundTime(placeCuDTO.getEarlyRefundTime());
                }
                if (!ObjectUtil.equals(existingPlace.getReminder(), placeCuDTO.getReminder())) {
                    existingPlace.setReminder(placeCuDTO.getReminder());
                }
                if (!ObjectUtil.equals(existingPlace.getBuyLimit(), placeCuDTO.getBuyLimit())) {
                    existingPlace.setBuyLimit(placeCuDTO.getBuyLimit());
                }
                baseMapper.updateById(existingPlace);
            }
        }

        // 提前收集所有新的分类ID
        Set<String> newCategoryIds = appSiteCategoryRuleDTOS.stream()
                .map(AppSiteCategoryRuleDTO::getCategoryId)
                .collect(Collectors.toSet());

        // 删除不在新分类列表中的现有场地
        existingPlaces.forEach(place -> {
            if (!newCategoryIds.contains(place.getCategoryId())) {
                baseMapper.deleteById(place);
            }
        });

        // 预加载所有相关的时间规则
        Map<String, List<AppSiteRuleTime>> categoryRuleTimeMap = new HashMap<>();
        for (String categoryId : newCategoryIds) {
            List<AppSiteRuleTime> rules = appSiteRuleTimeMapper.selectList(
                    Wrappers.<AppSiteRuleTime>lambdaQuery()
                            .eq(AppSiteRuleTime::getSiteId, site.getId())
                            .eq(AppSiteRuleTime::getCategoryId, categoryId));
            categoryRuleTimeMap.put(categoryId, rules);
        }

        for (AppSiteCategoryRuleDTO appSiteCategoryRuleDTO : appSiteCategoryRuleDTOS) {
            String categoryId = appSiteCategoryRuleDTO.getCategoryId();
            Integer count = appSiteCategoryRuleDTO.getCount();

            AppCategory category = appCategoryMapper.selectById(categoryId);
            if (category == null) {
                throw new JeecgBootException("分类不存在", SC_INTERNAL_SERVER_ERROR_500);
            }

            List<AppSitePlace> sitePlaces = existingPlaces.stream()
                    .filter(p -> p.getCategoryId() != null && p.getCategoryId().equals(categoryId))
                    .collect(Collectors.toList());

            if (sitePlaces.isEmpty()) {
                createNewPlaces(placeCuDTO, site, category, count,appSitePlaceParkDTO.getAppSitePlaceCuDTO());
                sitePlaces = baseMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery()
                        .eq(AppSitePlace::getSiteId, site.getId())
                        .eq(AppSitePlace::getCategoryId, category.getId()));
            }

            handleRuleTimeChanges(site, category, appSiteCategoryRuleDTO, categoryRuleTimeMap.getOrDefault(categoryId, Collections.emptyList()));

            adjustPlaceCount(site, category, sitePlaces, count,appSitePlaceParkDTO.getAppSitePlaceCuDTO());
        }

        return Boolean.TRUE;
    }

    private void createNewPlaces(AppSitePlaceCuDTO placeCuDTO, AppSite site, AppCategory category, Integer count,AppSitePlaceCuDTO appSitePlaceCuDTO) {
        for (int i = 1; i <= count; i++) {
            AppSitePlace appSitePlace = new AppSitePlace();
            BeanUtils.copyProperties(placeCuDTO, appSitePlace);
            appSitePlace.setType(SitePlaceTypeEnum.PACKAGE.getCode());
            appSitePlace.setName(category.getName() + i);
            appSitePlace.setSiteId(site.getId());
            appSitePlace.setOrgCode(site.getOrgCode());
            appSitePlace.setTenantId(site.getTenantId());
            appSitePlace.setCategoryId(category.getId());
            appSitePlace.setRefundType(appSitePlaceCuDTO.getRefundType());
            appSitePlace.setEarlyRefundTime(appSitePlaceCuDTO.getEarlyRefundTime());
            appSitePlace.setBuyLimit(appSitePlaceCuDTO.getBuyLimit());
            appSitePlace.setReminder(appSitePlaceCuDTO.getReminder());
            baseMapper.insert(appSitePlace);
        }
    }

    private void handleRuleTimeChanges(AppSite site, AppCategory category,
                                       AppSiteCategoryRuleDTO appSiteCategoryRuleDTO,
                                       List<AppSiteRuleTime> dbRuleTimes) {
        List<String> formIds = appSiteCategoryRuleDTO.getAppSiteRuleTimeFormDTOList().stream()
                .map(AppSiteRuleTimeFormDTO::getId)
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());

        List<String> dbIds = dbRuleTimes.stream()
                .map(AppSiteRuleTime::getId)
                .collect(Collectors.toList());

        // 删除旧规则
        List<String> toDelete = getDifferListByMap(dbIds, formIds);
        if (!toDelete.isEmpty()) {
            toDelete.forEach(id -> {
                appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSiteRuleTimeId, id));
            });
            appSiteRuleTimeMapper.deleteBatchIds(toDelete);
        }

        // 处理新增和修改
        for (AppSiteRuleTimeFormDTO formDTO : appSiteCategoryRuleDTO.getAppSiteRuleTimeFormDTOList()) {
            if (StrUtil.isBlank(formDTO.getId())) {
                insertNewRuleTime(site, category, formDTO);
            } else {
                updateExistingRuleTime(site, category, formDTO);
            }
        }
    }

    private void insertNewRuleTime(AppSite site, AppCategory category, AppSiteRuleTimeFormDTO formDTO) {
        AppSiteRuleTime appSiteRuleTime = new AppSiteRuleTime();
        appSiteRuleTime.setSiteId(site.getId())
                .setCategoryId(category.getId())
                .setStartTime(formDTO.getStartTime())
                .setEndTime(formDTO.getEndTime());
        appSiteRuleTimeMapper.insert(appSiteRuleTime);

        formDTO.getAppSiteRuleDTOList().forEach(ruleDTO -> {
            ruleDTO.setSiteRuleTimeId(appSiteRuleTime.getId());
        });

        // 批量插入价格规则
        List<AppSitePriceRules> priceRules = buildPriceRulesFromForm(site, category, appSiteRuleTime.getId(), formDTO.getAppSiteRuleDTOList());
        if (CollUtil.isNotEmpty(priceRules)) {
            appSitePriceRulesMapper.insertList(priceRules);
        }
    }

    private void updateExistingRuleTime(AppSite site, AppCategory category, AppSiteRuleTimeFormDTO formDTO) {
        AppSiteRuleTime appSiteRuleTime = appSiteRuleTimeMapper.selectById(formDTO.getId());
        if (appSiteRuleTime == null) return;

        appSiteRuleTime.setSiteId(site.getId())
                .setCategoryId(category.getId())
                .setStartTime(formDTO.getStartTime())
                .setEndTime(formDTO.getEndTime());
        appSiteRuleTimeMapper.updateById(appSiteRuleTime);

        List<AppSitePriceRules> dbPriceRules = appSitePriceRulesMapper.selectList(
                Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSiteRuleTimeId, appSiteRuleTime.getId()));

        for (AppSiteRuleDTO ruleDTO : formDTO.getAppSiteRuleDTOList()) {
            for (AppSitePriceRules dbRule : dbPriceRules) {
                if (Objects.equals(dbRule.getDayOfWeek(), ruleDTO.getDayOfWeek())) {
                    dbRule.setStartTime(ruleDTO.getStartTime())
                            .setEndTime(ruleDTO.getEndTime())
                            .setSellingPrice(ruleDTO.getSellingPrice());
                    appSitePriceRulesMapper.updateById(dbRule);
                }
            }
        }
    }

    private List<AppSitePriceRules> buildPriceRulesFromForm(AppSite site, AppCategory category, String ruleTimeId, List<AppSiteRuleDTO> ruleDTOs) {
        List<AppSitePriceRules> result = new ArrayList<>();
        for (AppSiteRuleDTO dto : ruleDTOs) {
            AppSitePriceRules rule = new AppSitePriceRules();
            BeanUtils.copyProperties(dto, rule);
            rule.setId(null);
            rule.setSiteRuleTimeId(ruleTimeId);
            rule.setOrgCode(site.getOrgCode());
            rule.setTenantId(site.getTenantId());
            rule.setCategoryId(category.getId());
            rule.setType(SitePlaceTypeEnum.PACKAGE.getCode());
            rule.setStatus(CommonConstant.STATUS_0_INT);
            rule.setDelFlag(CommonConstant.STATUS_0_INT);
            result.add(rule);
        }
        return result;
    }

    private void adjustPlaceCount(AppSite site, AppCategory category, List<AppSitePlace> sitePlaces, Integer targetCount,AppSitePlaceCuDTO appSitePlaceCuDTO) {
        long currentCount = sitePlaces.size();
        if (currentCount < targetCount) {
            addMorePlaces(site, category, sitePlaces, (int)(targetCount - currentCount),appSitePlaceCuDTO);
        } else if (currentCount > targetCount) {
            removeExcessPlaces(site, category, (int)(currentCount - targetCount));
        }
    }

    private void addMorePlaces(AppSite site, AppCategory category, List<AppSitePlace> sitePlaces, int numToAdd,AppSitePlaceCuDTO appSitePlaceCuDTO) {
        for (int i = 1; i <= numToAdd; i++) {
            AppSitePlace place = new AppSitePlace();
            BeanUtils.copyProperties(site, place);
            place.setSiteId(site.getId())
                    .setCategoryId(category.getId())
                    .setName(category.getName() + (sitePlaces.size() + i))
                    .setType(SitePlaceTypeEnum.PACKAGE.getCode())
                    .setOrgCode(site.getOrgCode())
                    .setRefundType(appSitePlaceCuDTO.getRefundType())
                    .setEarlyRefundTime(appSitePlaceCuDTO.getEarlyRefundTime())
                    .setBuyLimit(appSitePlaceCuDTO.getBuyLimit())
                    .setReminder(appSitePlaceCuDTO.getReminder())
                    .setTenantId(site.getTenantId());
            baseMapper.insert(place);
        }
    }

    private void removeExcessPlaces(AppSite site, AppCategory category, int numToRemove) {
        for (int i = 0; i < numToRemove; i++) {
            AppSitePlace placeToDelete = baseMapper.selectOne(Wrappers.<AppSitePlace>lambdaQuery()
                    .eq(AppSitePlace::getSiteId, site.getId())
                    .eq(AppSitePlace::getCategoryId, category.getId())
                    .orderByDesc(AppSitePlace::getId)
                    .last("LIMIT 1"));
            if (placeToDelete != null) {
                appSitePriceRulesMapper.delete(Wrappers.<AppSitePriceRules>lambdaQuery().eq(AppSitePriceRules::getSitePlaceId, placeToDelete.getId()));
                baseMapper.deleteById(placeToDelete);
            }
        }
    }
}
