package cn.iocoder.yudao.module.member.service.activitytable;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.member.api.activitypay.dto.MenuDTO;
import cn.iocoder.yudao.module.member.controller.admin.activityrestaurant.vo.ActivityRestaurantSaveReqVO;
import cn.iocoder.yudao.module.member.controller.admin.activitytable.vo.*;
import cn.iocoder.yudao.module.member.controller.app.activity.vo.AppCheckVO;
import cn.iocoder.yudao.module.member.controller.app.activity.vo.AppUnbindVO;
import cn.iocoder.yudao.module.member.dal.dataobject.activitypay.ActivityPayDO;
import cn.iocoder.yudao.module.member.dal.dataobject.activitypaytable.ActivityPayTableDO;
import cn.iocoder.yudao.module.member.dal.dataobject.activitytable.ActivityTableDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.activitytable.ActivityTableMapper;
import cn.iocoder.yudao.module.member.service.activitypay.ActivityPayService;
import cn.iocoder.yudao.module.member.service.activitypaytable.ActivityPayTableService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.ACTIVITY_TABLE_NOT_EXISTS;

/**
 * 活动用餐桌子 Service 实现类
 *
 * @author 我是秦俊旗
 */
@Service
@Validated
public class ActivityTableServiceImpl implements ActivityTableService {

    @Resource
    private ActivityTableMapper activityTableMapper;
    @Resource
    private MemberUserService memberUserService;

    @Resource
    private ActivityPayService activityPayService;

    @Resource
    private ActivityPayTableService activityPayTableService;

    @Override
    public Long createActivityTable(ActivityTableSaveReqVO createReqVO) {
        // 插入
        ActivityTableDO activityTable = BeanUtils.toBean(createReqVO, ActivityTableDO.class);
        activityTableMapper.insert(activityTable);
        // 返回
        return activityTable.getId();
    }

    @Override
    public void updateActivityTable(ActivityTableSaveReqVO updateReqVO) {
        // 校验存在
        validateActivityTableExists(updateReqVO.getId());
        // 更新
        ActivityTableDO updateObj = BeanUtils.toBean(updateReqVO, ActivityTableDO.class);
        activityTableMapper.updateById(updateObj);
    }

    @Override
    public void deleteActivityTable(Long id) {
        // 校验存在
        validateActivityTableExists(id);
        // 删除
        activityTableMapper.deleteById(id);
    }

    private void validateActivityTableExists(Long id) {
        if (activityTableMapper.selectById(id) == null) {
            throw exception(ACTIVITY_TABLE_NOT_EXISTS);
        }
    }

    @Override
    public ActivityTableDO getActivityTable(Long id) {
        return activityTableMapper.selectById(id);
    }

    @Override
    public PageResult<ActivityTableDO> getActivityTablePage(ActivityTablePageReqVO pageReqVO) {
        return activityTableMapper.selectPage(pageReqVO);
    }

    @Override
    public Map<Long, ActivityTableCountVO> countByActivityIds(List<Long> activityIds) {
        List<ActivityTableCountVO> activityTableCountVOS = activityTableMapper.countByActivityIds(activityIds);
        if (activityTableCountVOS.isEmpty()) {
            return Collections.emptyMap();
        }
        return activityTableCountVOS.stream().collect(Collectors.toMap(ActivityTableCountVO::getActivityId, v -> v));
    }

    @Override
    public void createByRestaurant(ActivityRestaurantSaveReqVO activityRestaurantSaveReqVO) {
        Integer totalTable = activityRestaurantSaveReqVO.getTotalTable();
        ArrayList<ActivityTableDO> activityTableDOS = new ArrayList<>();
        for (int i = 1; i <= totalTable; i++) {
            ActivityTableDO activityTableDO = new ActivityTableDO();
            activityTableDO.setActivityId(activityRestaurantSaveReqVO.getActivityId());
            activityTableDO.setSerialNumber(i);
            activityTableDO.setPrice(activityRestaurantSaveReqVO.getPrice());
            activityTableDOS.add(activityTableDO);
        }
        activityTableMapper.insertBatch(activityTableDOS);
    }

    @Override
    public void deleteByActivityId(Long activityId) {
        activityTableMapper.deleteByActivityId(activityId);
    }

    @Override
    public List<ActivityTableDO> getListByActivityIdAndTime(Long activityId, String time) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.parse(time, formatter);
        return activityTableMapper.selectList(Wrappers.lambdaQuery(ActivityTableDO.class)
                .eq(ActivityTableDO::getReserveTime, localDate)
                .eq(ActivityTableDO::getType, "0")
                .eq(ActivityTableDO::getActivityId, activityId));
    }

    @Override
    public synchronized Boolean userTableCheck(AppCheckVO vo) {

        if(CollectionUtil.isEmpty(vo.getMenuList())){
            throw exception(new ErrorCode(1_005_000_01, "请选择桌号"));
        }
        List<String> collect = vo.getMenuList().stream().map(MenuDTO::getSerialNumbers).collect(Collectors.toList());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.parse(vo.getTime(), formatter);
        List<ActivityTableDO> activityTableDOS = activityTableMapper.selectList(Wrappers.lambdaQuery(ActivityTableDO.class)
                .eq(ActivityTableDO::getReserveTime, localDate)
                .eq(ActivityTableDO::getActivityId, vo.getActivityId())
                .eq(ActivityTableDO::getType, "0")
                .in(ActivityTableDO::getSerialNumber, collect));

        if (!activityTableDOS.isEmpty()) {
            String result = activityTableDOS.stream()
                    .map(ActivityTableDO::getSerialNumber)        // 将Integer转为String
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            throw exception(new ErrorCode(1_005_000_02, result + "号桌子已预订"));
        }
        List<ActivityTableDO> addList = new ArrayList<>();
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        MemberUserDO user = memberUserService.getUser(loginUserId);
//        BigDecimal divide = vo.getPrice().divide(new BigDecimal(vo.getSerialNumbers().size()), 2, RoundingMode.HALF_UP);
        for (MenuDTO menu : vo.getMenuList()) {
            ActivityTableDO activityTableDO = new ActivityTableDO();
            activityTableDO.setUserId(loginUserId);
            activityTableDO.setMobile(user.getMobile());
            activityTableDO.setNickName(user.getNickname());
            activityTableDO.setAvatar(user.getAvatar());
            activityTableDO.setActivityId(vo.getActivityId());
            activityTableDO.setSerialNumber(Integer.valueOf(menu.getSerialNumbers()));
            activityTableDO.setPrice(BigDecimal.ZERO);
            activityTableDO.setReserveTime(localDate);
            activityTableDO.setMenuId(menu.getMenuId());
            activityTableDO.setMenuName(menu.getMenuName());
            addList.add(activityTableDO);
        }
        activityTableMapper.insertBatch(addList);
        return true;
    }

    @Override
    public Boolean userTableUnbind(AppUnbindVO vo) {
        if(vo.getSerialNumbers().isEmpty()){
            return true;
        }
        int update = activityTableMapper.delete(Wrappers.<ActivityTableDO>lambdaUpdate()
                .in(ActivityTableDO::getSerialNumber, vo.getSerialNumbers())
                .eq(ActivityTableDO::getActivityId, vo.getActivityId())
        );
        return update > 0;
    }

    @Override
    public List<ActivityTableDO> getListByActivityId(Long activityId) {
        return activityTableMapper.selectList(Wrappers.lambdaQuery(ActivityTableDO.class)
                .eq(ActivityTableDO::getActivityId, activityId));
    }

    @Override
    public List<ActivityTableDO> getListByActivityIdAndTimeAndUserId(Long activityId, LocalDate time, Long userId) {

        return activityTableMapper.selectList(Wrappers.lambdaQuery(ActivityTableDO.class)
                .eq(ActivityTableDO::getActivityId, activityId)
                .eq(ActivityTableDO::getReserveTime, time)
                .eq(ActivityTableDO::getUserId, userId)
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createActivityTableFalse(ActivityTableCreateVO createReqVO) {

        ActivityTableDO activityTable = BeanUtils.toBean(createReqVO, ActivityTableDO.class);
        activityTable.setPrice(BigDecimal.ZERO);
//        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        activityTable.setUserId(408L);
//        MemberUserDO user = memberUserService.getUser(loginUserId);
//        activityTable.setMobile(user.getMobile());
        activityTable.setNickName("管理员");
//        activityTable.setAvatar(user.getAvatar());

        activityTableMapper.insert(activityTable);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.parse(createReqVO.getReserveTime(), formatter);

        ActivityPayDO activityPaySaveReqVO = new ActivityPayDO();
        activityPaySaveReqVO.setActivityId(createReqVO.getActivityId());
        activityPaySaveReqVO.setPrice(BigDecimal.ZERO);
        activityPaySaveReqVO.setSerialNumbers(activityTable.getSerialNumber().toString());
        activityPaySaveReqVO.setUserId(408L);
        activityPaySaveReqVO.setStatus("1");
        activityPaySaveReqVO.setReserveTime(localDate);
        activityPaySaveReqVO.setNickName("管理员");
//        activityPaySaveReqVO.setMobile(user.getMobile());

        activityPayService.insertOne(activityPaySaveReqVO);

        ActivityPayTableDO activityPayTableDO = new ActivityPayTableDO();
        activityPayTableDO.setActivityId(createReqVO.getActivityId());
        activityPayTableDO.setPrice(BigDecimal.ZERO);
        activityPayTableDO.setSerialNumbers(activityTable.getSerialNumber().toString());
        activityPayTableDO.setUserId(408L);
        activityPayTableDO.setReserveTime(localDate);
        activityPayTableDO.setNickName("管理员");
//        activityPayTableDO.setMobile(user.getMobile());

        activityPayTableService.insertOne(activityPayTableDO);


        return activityTable.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTime(UpdateTimeVO updateTimeVO) {

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.parse(updateTimeVO.getReserveTime(), formatter);

        ActivityTableDO activityTableDO = activityTableMapper.selectById(updateTimeVO.getId());
        if (activityTableDO == null) {
            throw exception(new ErrorCode(1_005_000_02,  "订单不存在"));
        }

        ActivityPayDO oneByActivityIdAndTimeAndNum = activityPayService.getOneByActivityIdAndTimeAndNum(activityTableDO.getActivityId(), activityTableDO.getReserveTime(), activityTableDO.getSerialNumber());
        if (oneByActivityIdAndTimeAndNum == null) {
            throw exception(new ErrorCode(1_005_000_02, "订单不存在"));
        }

        ActivityPayTableDO oneByActivityIdAndTimeAndNum1 = activityPayTableService.getOneByActivityIdAndTimeAndNum(activityTableDO.getActivityId(), activityTableDO.getReserveTime(), activityTableDO.getSerialNumber());
        if (oneByActivityIdAndTimeAndNum1 == null) {
            throw exception(new ErrorCode(1_005_000_02, "订单不存在"));
        }

        activityTableDO.setReserveTime(localDate);
        oneByActivityIdAndTimeAndNum.setReserveTime(localDate);
        oneByActivityIdAndTimeAndNum1.setReserveTime(localDate);

        int i = activityTableMapper.updateById(activityTableDO);

        activityPayService.updateOne(oneByActivityIdAndTimeAndNum);

        activityPayTableService.updateOne(oneByActivityIdAndTimeAndNum1);

        return i > 0;
    }
}