package cn.iocoder.yudao.module.system.service.carteen;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.controller.admin.carteen.vo.CarteenPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.carteen.vo.CarteenSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.carteen.vo.CarteenSerialSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.carteen.vo.CarteenWeekSalesRespVo;
import cn.iocoder.yudao.module.system.dal.dataobject.carteen.CarteenDO;
import cn.iocoder.yudao.module.system.dal.mysql.carteen.CarteenMapper;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 门店管理 Service 实现类
 *
 * @author 开发账号
 */
@Service
@Validated
public class CarteenServiceImpl implements CarteenService {

    @Resource
    private CarteenMapper carteenMapper;
    @Resource
    private PermissionService permissionService;
    private static final String ALL="all";
    //这周字段
    private static final String THISWEEK="week";
    //上周
    private static final String LASTWEEK="LastWeek";

    @Override
    public Long createCarteen(CarteenSaveReqVO createReqVO) {
        // 插入
        CarteenDO carteen = BeanUtils.toBean(createReqVO, CarteenDO.class);
        carteen.setDeleted(Boolean.FALSE);
        carteen.setMultipleManage(Boolean.FALSE);
        carteen.setAccountOrder(Boolean.FALSE);
        carteen.setDeleted(Boolean.FALSE);
        carteen.setSerialNumber(String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        carteenMapper.insert(carteen);
        // 返回
        return carteen.getId();
    }
    @Override
    public void updateCarteen(CarteenSaveReqVO updateReqVO) {
        // 校验存在
        validateCarteenExists(updateReqVO.getId());
        // 更新
        CarteenDO updateObj = BeanUtils.toBean(updateReqVO, CarteenDO.class);
        carteenMapper.updateById(updateObj);
    }

    @Override
    public void deleteCarteen(Long id) {
        // 校验存在
        validateCarteenExists(id);
        // 删除
        carteenMapper.deleteById(id);
    }

    private void validateCarteenExists(Long id) {
        if (carteenMapper.selectById(id) == null) {
            throw exception(ErrorCodeConstants.CARTEEN_NOT_EXISt);
        }
    }

    @Override
    public CarteenDO getCarteen(Long id) {
        return carteenMapper.selectById(id);
    }

    @Override
    public PageResult<CarteenDO> getCarteenPage(CarteenPageReqVO pageReqVO) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        return carteenMapper.selectPage(pageReqVO,loginUserId);
    }
    /**
     * @param req
     * @return
     * @Description: 获取门店一周卖出多少销量 千克
     * @Author: qjq
     * @Date: 2024/4/19 上午9:55
     */
    @Override
    public Map<String, List<CarteenWeekSalesRespVo>> getCarteenWeekSales(CarteenPageReqVO req) {
        //获取这周时间
        DateTime endTime =DateUtil.endOfDay(DateUtil.date());
        DateTime startTime1=DateUtil.beginOfDay(endTime);
        //获取偏移时间单位
        DateTime startTime=DateUtil.offsetDay(startTime1,-6);
        //获取上周时间
        DateTime endTime2=DateUtil.endOfDay(DateUtil.offsetDay(startTime,-1));
        DateTime startTime2 =DateUtil.beginOfDay(DateUtil.offsetDay(endTime2,-6));
        Map<String, List<CarteenWeekSalesRespVo>> listMap=new HashMap<>();
        //这周时间
        //获取所有门店的销售量
        List<CarteenWeekSalesRespVo> list = this.getCarteenWeekSalesByType(req, startTime, endTime);
        list.addAll(this.getCarteenSales(req, startTime1, endTime));
        if(ALL.equals(req.getType())){
            listMap.put(THISWEEK,this.getComputeCarteenWeekSales(list));
            //上周时间
            listMap.put(LASTWEEK,this.getCarteenWeekSalesByType(req, startTime2, endTime2));
        }else{
            listMap.put(THISWEEK,list);
            listMap.put(LASTWEEK,this.getCarteenWeekSalesByType(req, startTime2, endTime2));
        }
        //进行时间处理
        listMap.forEach((v,k)->{
            k.sort(Comparator.comparing(CarteenWeekSalesRespVo::getCreateTime));
            k.forEach(f-> f.setTimeType(LocalDateTimeUtil.dayOfWeek(f.getCreateTime().toLocalDate()).toChinese()));
        });
        return listMap;
    }
    public List<CarteenWeekSalesRespVo> getComputeCarteenWeekSales(List<CarteenWeekSalesRespVo> list) {
        List<CarteenWeekSalesRespVo> list1= new ArrayList<>();
        list.forEach(f-> f.setTimeType(LocalDateTimeUtil.dayOfWeek(f.getCreateTime().toLocalDate()).toChinese()));
        list.stream()
                .collect(Collectors.groupingBy(CarteenWeekSalesRespVo::getCarteenId))
                .forEach((k,v)->{
                    CarteenWeekSalesRespVo bean = BeanUtil.toBean(v.get(0), CarteenWeekSalesRespVo.class);
                    BigDecimal sum = v.stream()
                            .map(CarteenWeekSalesRespVo::getSales)
                            .filter(ObjectUtil::isNotEmpty)
                            .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
                    bean.setSales(sum);
                    list1.add(bean);
                });
        return list1;
    }
    public List<CarteenWeekSalesRespVo> getCarteenWeekSalesByType(CarteenPageReqVO req,
                                                                  DateTime startDate,
                                                                  DateTime endDate){
        if(ALL.equals(req.getType())){
            return this.getComputeCarteenWeekSales(carteenMapper.selectWeekSales(null,startDate,endDate));
        }else{

            return carteenMapper.selectWeekSales(req.getCarteenId(),startDate,endDate);
        }
    }
    /**
     * @Description: 今日门店销售量
     * @Author: qjq
     * @Date: 2024/4/19 上午11:35
     * @return
     */
    public List<CarteenWeekSalesRespVo> getCarteenSales(CarteenPageReqVO req, DateTime startDate,
                                                        DateTime endDate){
        if(ALL.equals(req.getType())){
            return carteenMapper.getCarteenSales(null,startDate,endDate);
        }
        else{
            return carteenMapper.getCarteenSales(req.getCarteenId(),startDate,endDate);
        }
    }

    /**
     * @param userId
     * @return
     * @Description: 根据用户编号获取门店
     * @Author: qjq
     * @Date: 2024/4/23 上午9:58
     */
    @Override
    public List<CarteenDO> getUserCarteem(Long userId) {
        //获取门店
        return carteenMapper.selectList(new LambdaQueryWrapperX<CarteenDO>()
                .last("and FIND_IN_SET(" + userId + ",serial_number) order by id desc")
        );
    }
    /**
     * @param req
     * @return
     * @Description: 修改门店那些用户可以看
     * @Author: qjq
     * @Date: 2024/4/23 上午10:37
     */
    @Override
    public Boolean updateUserCarteen(CarteenSerialSaveReqVO req) {
        int update = carteenMapper.update(new LambdaUpdateWrapper<CarteenDO>()
                .set(CarteenDO::getSerialNumber, req.getSerialNumber())
                .eq(CarteenDO::getId, req.getId())
        );
        return update>0?Boolean.TRUE:Boolean.FALSE;
    }

    /**
     * @return
     * @Description: 获取所有门店
     * @Author: qjq
     * @Date: 2024/4/23 下午1:47
     */
    @Override
    public List<CarteenDO> getCarteenList() {
        return carteenMapper.selectList(new LambdaQueryWrapperX<CarteenDO>()
                .eq(CarteenDO::getDeleted,Boolean.FALSE));
    }
}