package com.tourism.webadmin.back.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.Page;
import com.tourism.common.core.base.dao.BaseDaoMapper;
import com.tourism.common.core.base.service.BaseService;
import com.tourism.common.core.constant.ErrorCodeEnum;
import com.tourism.common.core.constant.GlobalDeletedFlag;
import com.tourism.common.core.exception.MyRuntimeException;
import com.tourism.common.core.object.CallResult;
import com.tourism.common.core.object.MyRelationParam;
import com.tourism.common.core.util.MyDateUtil;
import com.tourism.common.core.util.MyModelUtil;
import com.tourism.common.sequence.wrapper.IdGeneratorWrapper;
import com.tourism.webadmin.app.website.dto.TourCalcTotalAmountParam;
import com.tourism.webadmin.app.website.dto.TourProjectGroupPurchaseDtoToWebDto;
import com.tourism.webadmin.app.website.dto.TourismBookProjectDto;
import com.tourism.webadmin.back.dao.TourProjectGroupPurchaseMapper;
import com.tourism.webadmin.back.model.TourOrder;
import com.tourism.webadmin.back.model.TourProjectGroupPurchase;
import com.tourism.webadmin.back.model.TourProjectGroupPurchaseDetail;
import com.tourism.webadmin.back.service.TourProjectGroupPurchaseDetailService;
import com.tourism.webadmin.back.service.TourProjectGroupPurchaseService;
import com.tourism.webadmin.back.service.TourismProjectService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 拼团设置主表数据操作服务类。
 *
 * @author 吃饭睡觉
 * @date 2024-09-06
 */
@Slf4j
@Service("tourProjectGroupPurchaseService")
public class TourProjectGroupPurchaseServiceImpl extends BaseService<TourProjectGroupPurchase, Long> implements TourProjectGroupPurchaseService {

    @Autowired
    private IdGeneratorWrapper idGenerator;
    @Autowired
    private TourProjectGroupPurchaseMapper tourProjectGroupPurchaseMapper;
    @Autowired
    private TourismProjectService tourismProjectService;
    @Autowired
    private TourProjectGroupPurchaseDetailService tourProjectGroupPurchaseDetailService;

    /**
     * 返回当前Service的主表Mapper对象。
     *
     * @return 主表Mapper对象。
     */
    @Override
    protected BaseDaoMapper<TourProjectGroupPurchase> mapper() {
        return tourProjectGroupPurchaseMapper;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TourProjectGroupPurchase saveNew(TourProjectGroupPurchase tourProjectGroupPurchase) {
        tourProjectGroupPurchaseMapper.insert(this.buildDefaultValue(tourProjectGroupPurchase));
        return tourProjectGroupPurchase;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveNewBatch(List<TourProjectGroupPurchase> tourProjectGroupPurchaseList) {
        if (CollUtil.isNotEmpty(tourProjectGroupPurchaseList)) {
            tourProjectGroupPurchaseList.forEach(this::buildDefaultValue);
            tourProjectGroupPurchaseMapper.insertList(tourProjectGroupPurchaseList);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean update(TourProjectGroupPurchase tourProjectGroupPurchase, TourProjectGroupPurchase originalTourProjectGroupPurchase) {
        MyModelUtil.fillCommonsForUpdate(tourProjectGroupPurchase, originalTourProjectGroupPurchase);
        // 这里重点提示，在执行主表数据更新之前，如果有哪些字段不支持修改操作，请用原有数据对象字段替换当前数据字段。
        UpdateWrapper<TourProjectGroupPurchase> uw = this.createUpdateQueryForNullValue(tourProjectGroupPurchase, tourProjectGroupPurchase.getId());
        return tourProjectGroupPurchaseMapper.update(tourProjectGroupPurchase, uw) == 1;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean remove(Long id) {
        return tourProjectGroupPurchaseMapper.deleteById(id) == 1;
    }

    @Override
    public List<TourProjectGroupPurchase> getTourProjectGroupPurchaseList(TourProjectGroupPurchase filter, String orderBy) {
        return tourProjectGroupPurchaseMapper.getTourProjectGroupPurchaseList(filter, orderBy);
    }

    @Override
    public List<TourProjectGroupPurchase> getTourProjectGroupPurchaseListWithRelation(TourProjectGroupPurchase filter, String orderBy) {
        List<TourProjectGroupPurchase> resultList = tourProjectGroupPurchaseMapper.getTourProjectGroupPurchaseList(filter, orderBy);
        // 在缺省生成的代码中，如果查询结果resultList不是Page对象，说明没有分页，那么就很可能是数据导出接口调用了当前方法。
        // 为了避免一次性的大量数据关联，规避因此而造成的系统运行性能冲击，这里手动进行了分批次读取，开发者可按需修改该值。
        int batchSize = resultList instanceof Page ? 0 : 1000;
        this.buildRelationForDataList(resultList, MyRelationParam.normal(), batchSize);
        return resultList;
    }

    @Override
    public CallResult verifyRelatedDataBeforeDelete(TourProjectGroupPurchase tourProjectGroupPurchase) {
        TourProjectGroupPurchaseDetail tourProjectGroupPurchaseDetail = new TourProjectGroupPurchaseDetail();
        tourProjectGroupPurchaseDetail.setGroupPurchaseCode(tourProjectGroupPurchase.getCode());
        if (tourProjectGroupPurchaseDetailService.getCountByFilter(tourProjectGroupPurchaseDetail) > 0) {
            // NOTE: 可以根据需求修改下面方括号中的提示信息。
            return CallResult.error("数据验证失败，[TourProjectGroupPurchaseDetail] 存在关联数据！");
        }
        return CallResult.ok();
    }

    @Override
    public CallResult verifyRelatedData(TourProjectGroupPurchase tourProjectGroupPurchase, TourProjectGroupPurchase originalTourProjectGroupPurchase) {
        String errorMessageFormat = "数据验证失败，关联的%s并不存在，请刷新后重试！";
        //这里是基于字典的验证。
        if (this.needToVerify(tourProjectGroupPurchase, originalTourProjectGroupPurchase, TourProjectGroupPurchase::getProjectId)
                && !tourismProjectService.existId(String.valueOf(tourProjectGroupPurchase.getProjectId()))) {
            return CallResult.error(String.format(errorMessageFormat, "项目id"));
        }
        //这里是一对多的验证
        if (this.needToVerify(tourProjectGroupPurchase, originalTourProjectGroupPurchase, TourProjectGroupPurchase::getCode)
                && !tourProjectGroupPurchaseDetailService.existOne("groupPurchaseCode", tourProjectGroupPurchase.getCode())) {
            return CallResult.error(String.format(errorMessageFormat, "关联字段(与从表)"));
        }
        return CallResult.ok();
    }

    @Override
    public List<TourProjectGroupPurchase> getLowestPriceGroupPurchase(List<Long> projectIds) {
        if(CollUtil.isEmpty(projectIds)) return new ArrayList<>();
        return tourProjectGroupPurchaseMapper.getLowestPriceGroupPurchaseList(projectIds, LocalDate.now());
    }

    @Override
    public List<String> queryUniqueGroupPurchaseDates(TourProjectGroupPurchaseDtoToWebDto dto) {
        LambdaQueryWrapper<TourProjectGroupPurchase> queryWrapper = new LambdaQueryWrapper<>();

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        // 查询条件：根据 project_id 和 end_time 筛选
        queryWrapper.eq(TourProjectGroupPurchase::getProjectId, dto.getProjectId())
                .eq(TourProjectGroupPurchase::getState, 1)  // 只查启用状态的记录
//                .ne(TourProjectGroupPurchase::getDataState, -1)  // 排除已删除的记录
                .ge(TourProjectGroupPurchase::getEndTime, format.format(new Date()))
                .ge(dto.getTravelStartTimeStart() != null, TourProjectGroupPurchase::getTravelStartTime, dto.getTravelStartTimeStart())
                .le(dto.getTravelStartTimeEnd() != null, TourProjectGroupPurchase::getTravelStartTime, dto.getTravelStartTimeEnd())
                .orderBy(true, true, TourProjectGroupPurchase::getTravelStartTime); // 按照拼团结束时间筛选

        // 查询出符合条件的出行开始时间
        queryWrapper.select(TourProjectGroupPurchase::getTravelStartTime);

        // 执行查询，获取符合条件的结果
        List<TourProjectGroupPurchase> groupPurchases = tourProjectGroupPurchaseMapper.selectList(queryWrapper);

        // 创建另一个 SimpleDateFormat 对象来格式化为新的格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        // 返回去重后的出行开始时间，转为字符串形式
        return groupPurchases.stream()
                .map(item -> sdf.format(item.getTravelStartTime()))
                .distinct()  // 去重
                .collect(Collectors.toList());
    }

    @Override
    public TourProjectGroupPurchase handleGroupBuy(TourismBookProjectDto paramDTO, TourOrder tourOrder) {
        TourProjectGroupPurchase groupPurchase = this.getById(paramDTO.getGroupId());
        if (groupPurchase != null) {
            // 先判断下拼团信息是不是过期了  由于这里默认是yyyy-MM-dd 00:00:00  所以要加一天
            Date newDate = MyDateUtil.addDays(groupPurchase.getEndTime(), 1);
            if (newDate.getTime() < System.currentTimeMillis()) {
                throw new MyRuntimeException(ErrorCodeEnum.GROUP_BUYING_HAS_EXPIRED.getErrorMessage());
            }
        }else {
            throw new MyRuntimeException(ErrorCodeEnum.GROUP_BUYING_DOES_NOT_EXIST.getErrorMessage());
        }

        // 计算此次订单参加拼团人数
        Integer groupCount = paramDTO.getAdultNumber() + paramDTO.getChildrenNumber();

        if(groupCount > groupPurchase.getMaxCount()){
            throw new MyRuntimeException(ErrorCodeEnum.PEOPLE_EXCCEDS.getErrorMessage());
        }
        //  2024-01-08逻辑修改 // 判断人数是不是超了，如果超了或者人数满了，自动开个完全一样的新团，直接在新团上加数量
        // 如果超过团购人数，则需要提醒已经满团，不允许客户继续参团
        if(groupCount + groupPurchase.getNowCount() > groupPurchase.getMaxCount()) {
            throw new MyRuntimeException(ErrorCodeEnum.FULL_GROUP_ERROR.getErrorMessage());
        } else if (groupCount + groupPurchase.getNowCount() == groupPurchase.getMaxCount()) {
            groupPurchase.setNowCount(groupCount + groupPurchase.getNowCount());
            groupPurchase.setSuccess(1);
            groupPurchase.setNowPrice(groupPurchase.getAdultPrice());
            groupPurchase.setNextPrice(groupPurchase.getAdultPrice());
            groupPurchase.setNextStageNum(0);
            groupPurchase = tourProjectGroupPurchaseDetailService.getNowPriceAndNextStagePrice(groupPurchase);
            this.updateById(groupPurchase);
        }else {
            groupPurchase.setNowCount(groupCount + groupPurchase.getNowCount());
            // 拼团后修改团购的当前价格、下阶段价格、距离下阶段人数
            groupPurchase = tourProjectGroupPurchaseDetailService.getNowPriceAndNextStagePrice(groupPurchase);
            this.updateById(groupPurchase);
        }
        tourOrder.setType(1);
        // 计算订单价格
        BigDecimal adultTotalPrice = groupPurchase.getNowPrice().multiply(BigDecimal.valueOf(tourOrder.getAdultNumber() == null? 0 : tourOrder.getAdultNumber()));
        BigDecimal childTotalPrice = groupPurchase.getNowChildPrice().multiply(BigDecimal.valueOf(tourOrder.getChildrenNumber() == null ? 0 : tourOrder.getChildrenNumber()));

        tourOrder.setTotalAmount(adultTotalPrice.add(childTotalPrice));
        tourOrder.setCurrency(groupPurchase.getPriceUnit());
        tourOrder.setAdultPrice(groupPurchase.getNowPrice());
        tourOrder.setChildrenPrice(groupPurchase.getNowChildPrice());
        tourOrder.setGroupPurchaseProgressId(groupPurchase.getId());
        return groupPurchase;
    }

    @Override
    public Map<String, Object> calcTotalAmount(TourCalcTotalAmountParam param) {
        TourProjectGroupPurchase groupPurchase = this.getById(param.getId());
        Integer groupCount = param.getAdultCount() + param.getChildrenCount() + groupPurchase.getNowCount();
        if(groupCount > groupPurchase.getMaxCount()){
            throw new MyRuntimeException(ErrorCodeEnum.PEOPLE_EXCCEDS.getErrorMessage());
        }
        groupPurchase.setNowCount(param.getAdultCount() + param.getChildrenCount() + groupPurchase.getNowCount());
        // 计算增加人数后的团购价格
        TourProjectGroupPurchase nowPriceAndNextStagePrice = tourProjectGroupPurchaseDetailService.getNowPriceAndNextStagePrice(groupPurchase);

        BigDecimal adultTotalPrice = nowPriceAndNextStagePrice.getNowPrice().multiply(BigDecimal.valueOf(param.getAdultCount()));
        BigDecimal childrenTotalPrice = nowPriceAndNextStagePrice.getNowChildPrice().multiply(BigDecimal.valueOf(param.getChildrenCount()));
        BigDecimal totalPrice = adultTotalPrice.add(childrenTotalPrice);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("totalPrice", totalPrice);
        return resultMap;
    }

    @Override
    public TourProjectGroupPurchase cancelGroupBuy(TourProjectGroupPurchase groupPurchase, TourOrder tourOrder) {
        // 在团购中减去订单的人数
        groupPurchase.setNowCount(groupPurchase.getNowCount() - tourOrder.getAdultNumber() - tourOrder.getChildrenNumber());
        // 重新计算拼团当前价格、下一阶段价格、距离下一阶段数量
        groupPurchase = tourProjectGroupPurchaseDetailService.getNowPriceAndNextStagePrice(groupPurchase);

        tourOrder.setAdultPrice(groupPurchase.getNowPrice());
        tourOrder.setChildrenPrice(groupPurchase.getNowChildPrice());
        // 修改团购当前参团人数、当前价格、下一阶段价格、距离下一阶段数量
        this.updateById(groupPurchase);
        return groupPurchase;
    }

    private TourProjectGroupPurchase buildDefaultValue(TourProjectGroupPurchase tourProjectGroupPurchase) {
        if (tourProjectGroupPurchase.getId() == null) {
            tourProjectGroupPurchase.setId(idGenerator.nextLongId());
            tourProjectGroupPurchase.setCode(idGenerator.nextLongId());
        }
        MyModelUtil.fillCommonsForInsert(tourProjectGroupPurchase);
        tourProjectGroupPurchase.setDataState(GlobalDeletedFlag.NORMAL);
        MyModelUtil.setDefaultValue(tourProjectGroupPurchase, "title", "");
        MyModelUtil.setDefaultValue(tourProjectGroupPurchase, "image", "");
        return tourProjectGroupPurchase;
    }
}
