package com.jsowell.pile.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.page.PageResponse;
import com.jsowell.common.enums.DelFlagEnum;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.ykcCommond.ReservationChargingCommand;
import com.jsowell.pile.dto.CreateReservedDTO;
import com.jsowell.pile.dto.PersonPileStopChargingDTO;
import com.jsowell.pile.dto.PileReservationDTO;
import com.jsowell.pile.dto.StartPersonPileDTO;
import com.jsowell.pile.service.MemberPlateNumberRelationService;
import com.jsowell.pile.service.PileBasicInfoService;
import com.jsowell.pile.service.PileRemoteService;
import com.jsowell.pile.vo.PileReservedVO;
import com.jsowell.pile.vo.uniapp.customer.MemberPlateNumberVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Time;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Objects;

import com.jsowell.pile.mapper.PileReservationInfoMapper;
import com.jsowell.pile.domain.PileReservationInfo;
import com.jsowell.pile.service.PileReservationInfoService;

@Slf4j
@Service
public class PileReservationInfoServiceImpl implements PileReservationInfoService {

    @Resource
    private PileReservationInfoMapper pileReservationInfoMapper;

    @Autowired
    private PileBasicInfoService pileBasicInfoService;

    @Autowired
    private PileRemoteService pileRemoteService;

    @Autowired
    private MemberPlateNumberRelationService memberPlateNumberRelationService;

    @Override
    public int deleteByPrimaryKey(Integer id) {
        return pileReservationInfoMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(PileReservationInfo record) {
        return pileReservationInfoMapper.insert(record);
    }

    @Override
    public int insertOrUpdate(PileReservationInfo record) {
        return pileReservationInfoMapper.insertOrUpdate(record);
    }

    @Override
    public int insertOrUpdateSelective(PileReservationInfo record) {
        return pileReservationInfoMapper.insertOrUpdateSelective(record);
    }

    @Override
    public int insertSelective(PileReservationInfo record) {
        return pileReservationInfoMapper.insertSelective(record);
    }

    @Override
    public PileReservationInfo selectByPrimaryKey(Integer id) {
        return pileReservationInfoMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(PileReservationInfo record) {
        return pileReservationInfoMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(PileReservationInfo record) {
        return pileReservationInfoMapper.updateByPrimaryKey(record);
    }

    @Override
    public int updateBatch(List<PileReservationInfo> list) {
        return pileReservationInfoMapper.updateBatch(list);
    }

    @Override
    public int batchInsert(List<PileReservationInfo> list) {
        return pileReservationInfoMapper.batchInsert(list);
    }

    @Override
    public int updateBatchSelective(List<PileReservationInfo> list) {
        return pileReservationInfoMapper.updateBatchSelective(list);
    }

    @Override
    public List<PileReservationInfo> getReservationsByMemberIdAndPileSn(String memberId, String pileSn) {
        return pileReservationInfoMapper.findByMemberIdAndPileSn(memberId, pileSn);
    }

    /**
     * 启用预约/开启预约/启动预约
     */
    @Override
    public void activateReserved(PileReservationDTO dto) {
        // 查询其他生效中的预约
        List<PileReservationInfo> infoList = pileReservationInfoMapper.findByMemberIdAndPileSnAndStatus(dto.getMemberId(), dto.getPileSn(), "1");
        if (CollectionUtils.isNotEmpty(infoList)) {
            throw new BusinessException(ReturnCodeEnum.CODE_RESERVATION_ALREADY_EXISTS_ERROR);
        }

        PileReservationInfo pileReservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.parseInt(dto.getReservedId()));
        if (pileReservationInfo == null) {
            return;
        }
        if (!StringUtils.equals(dto.getMemberId(), pileReservationInfo.getMemberId())) {
            return;
        }
        pileReservationInfo.setStatus(Constants.ONE);
        // 保存之前，校验时间是否重叠
        int i = saveReservation(pileReservationInfo);
        if (i > 0) {
            // 查询会员的绑定vin列表
            List<MemberPlateNumberVO> plateNumberVOList = memberPlateNumberRelationService.selectMemberPlateNumberRelation(pileReservationInfo.getMemberId());
            List<String> vinCodes = Lists.newArrayList();
            int count = 0;
            for (MemberPlateNumberVO vo : plateNumberVOList) {
                if (count < 3 && StringUtils.isNotBlank(vo.getVinCode())) {
                    vinCodes.add(vo.getVinCode());
                    count++;
                }
            }
            // 如果 vinCodes 的数量少于 3，用 "0" 补足
            while (vinCodes.size() < 3) {
                vinCodes.add("");
            }

            String type = StringUtils.equals(pileReservationInfo.getReservationType(), "single") ? "00" : "01";
            // 发送指令
            ReservationChargingCommand command = ReservationChargingCommand.builder()
                    .transactionCode(Constants.ILLEGAL_TRANSACTION_CODE)
                    .pileSn(pileReservationInfo.getPileSn())
                    .connectorCode(pileReservationInfo.getPileConnectorCode().replace(pileReservationInfo.getPileSn(), ""))
                    .operation("01")
                    .reservationType(type)
                    .vin1(vinCodes.get(0))
                    .vin2(vinCodes.get(1))
                    .vin3(vinCodes.get(2))
                    .reservedStartTime(pileReservationInfo.getStartTime().toLocalTime())
                    .reservedEndTime(pileReservationInfo.getEndTime().toLocalTime())
                    .amount(Constants.WHITELIST_DEFAULT_AMOUNT)
                    .build();
            pileRemoteService.reservationCharging(command);
        }
    }

    /**
     * 禁用预约
     */
    @Override
    public void deactivateReserved(PileReservationDTO dto) {
        PileReservationInfo pileReservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.parseInt(dto.getReservedId()));
        if (pileReservationInfo == null) {
            return;
        }
        if (!StringUtils.equals(dto.getMemberId(), pileReservationInfo.getMemberId())) {
            return;
        }
        // 校验通过可以修改预约
        pileReservationInfo.setStatus(Constants.ZERO);
        int i = pileReservationInfoMapper.updateByPrimaryKeySelective(pileReservationInfo);
        if (i > 0) {
            // 查询会员的绑定vin列表
            List<MemberPlateNumberVO> plateNumberVOList = memberPlateNumberRelationService.selectMemberPlateNumberRelation(pileReservationInfo.getMemberId());
            List<String> vinCodes = Lists.newArrayList();
            int count = 0;
            for (MemberPlateNumberVO vo : plateNumberVOList) {
                if (count < 3 && StringUtils.isNotBlank(vo.getVinCode())) {
                    vinCodes.add(vo.getVinCode());
                    count++;
                }
            }
            // 如果 vinCodes 的数量少于 3，用 "0" 补足
            while (vinCodes.size() < 3) {
                vinCodes.add("");
            }

            String type = StringUtils.equals(pileReservationInfo.getReservationType(), "single") ? "00" : "01";
            // 发送指令
            ReservationChargingCommand command = ReservationChargingCommand.builder()
                    .transactionCode(Constants.ILLEGAL_TRANSACTION_CODE)
                    .pileSn(pileReservationInfo.getPileSn())
                    .connectorCode(pileReservationInfo.getPileConnectorCode().replace(pileReservationInfo.getPileSn(), ""))
                    .operation("02")
                    .reservationType(type)
                    .vin1(vinCodes.get(0))
                    .vin2(vinCodes.get(1))
                    .vin3(vinCodes.get(2))
                    .reservedStartTime(pileReservationInfo.getStartTime().toLocalTime())
                    .reservedEndTime(pileReservationInfo.getEndTime().toLocalTime())
                    .amount(Constants.WHITELIST_DEFAULT_AMOUNT)
                    .build();
            pileRemoteService.reservationCharging(command);
        }
    }

    /**
     * 校验时间是否重叠
     * @param memberId
     * @param pileSn
     * @param startTime
     * @param endTime
     * @param reservationId
     * @return
     */
    public boolean isTimeSlotAvailable(String memberId, String pileSn, Time startTime, Time endTime, Integer reservationId) {
        List<PileReservationInfo> reservations = pileReservationInfoMapper.findByMemberIdAndPileSnAndStatus(memberId, pileSn, "1");
        LocalTime newStartTime = startTime.toLocalTime();
        LocalTime newEndTime = endTime.toLocalTime();

        for (PileReservationInfo res : reservations) {
            if (res.getId().equals(reservationId)) {
                continue; // Skip the current reservation if updating
            }
            LocalTime existingStartTime = res.getStartTime().toLocalTime();
            LocalTime existingEndTime = res.getEndTime().toLocalTime();

            if (newStartTime.isBefore(existingEndTime) && newEndTime.isAfter(existingStartTime)) {
                return false; // Time slot overlaps
            }
        }
        return true;
    }

    public int saveReservation(PileReservationInfo reservation) {
        if (isTimeSlotAvailable(reservation.getMemberId(), reservation.getPileSn(), reservation.getStartTime(), reservation.getEndTime(), reservation.getId())) {
            return this.updateByPrimaryKeySelective(reservation);
        } else {
            throw new BusinessException(ReturnCodeEnum.CODE_UPDATE_RESERVED_STATUS_REFUSED);
        }
    }

    /**
     * 根据充电枪口编号发送指令
     * @param pileConnectorCode
     */
    @Override
    public void pushReservedByPileConnectorCode(String pileConnectorCode) {
        // 根据充电枪口编号查询正在生效中的预约
        PileReservationInfo pileReservationInfo = pileReservationInfoMapper.selectActiveReservationByPileConnectorCode(pileConnectorCode);
        if (Objects.isNull(pileReservationInfo)) {
            return;
        }

        // 生成个人桩订单
        StartPersonPileDTO dto = new StartPersonPileDTO();
        dto.setPileConnectorCode(pileConnectorCode);
        dto.setMemberId(pileReservationInfo.getMemberId());
        LocalDateTime[] localDateTimes = DateUtils.convertStartAndEndTime(pileReservationInfo.getStartTime().toString(), pileReservationInfo.getEndTime().toString());
        dto.setStartTime(DateUtils.formatDateTime(localDateTimes[0]));
        dto.setEndTime(DateUtils.formatDateTime(localDateTimes[1]));
        pileBasicInfoService.startPersonalPileCharging(dto);
    }

    /**
     * 拔枪时，根据充电桩枪口编号关闭仅一次的预约
     * @param pileConnectorCode
     */
    @Override
    public void cancelOneTimeReservation(String pileConnectorCode) {
        // 根据充电枪口编号查询仅一次正在生效中的预约
    }

    @Override
    public void deleteReservation(PileReservationDTO dto) {
        PileReservationInfo pileReservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.valueOf(dto.getReservedId()));
        if (Objects.isNull(pileReservationInfo)) {
            return;
        }
        if (!StringUtils.equals(pileReservationInfo.getMemberId(), dto.getMemberId())) {
            return;
        }
        pileReservationInfo.setDelFlag(DelFlagEnum.DELETE.getValue());
        pileReservationInfoMapper.updateByPrimaryKey(pileReservationInfo);
    }

    @Override
    public int createReservation(CreateReservedDTO dto) {
        PileReservationInfo reservedInfo = new PileReservationInfo();
        reservedInfo.setMemberId(dto.getMemberId());
        reservedInfo.setPileSn(dto.getPileSn());
        reservedInfo.setPileConnectorCode(dto.getPileConnectorCode());
        reservedInfo.setStatus(Constants.ZERO); // 默认未生效
        // reservedInfo.setStartTime(DateUtils.parseDate(dto.getStartTime()));
        reservedInfo.setStartTime(Time.valueOf(dto.getStartTime()));
        // reservedInfo.setEndTime(DateUtils.parseDate(dto.getEndTime()));
        if (StringUtils.isNotBlank(dto.getEndTime())) {
            reservedInfo.setEndTime(Time.valueOf(dto.getEndTime()));
        }

        // 2024年7月25日14点36分, 此段代码注释掉, 采用默认设置
        // if (StringUtils.isNotBlank(dto.getFreq())) {
        // 	reservedInfo.setReservationType("recurring");
        // 	reservedInfo.setFreq(dto.getFreq());
        // } else {
        // 	reservedInfo.setReservationType("single");
        // 	reservedInfo.setFreq(null);
        // }

        // 默认每天
        reservedInfo.setReservationType("recurring");
        reservedInfo.setFreq("daily");

        reservedInfo.setCreateBy(dto.getMemberId());
        this.insertSelective(reservedInfo);
        return reservedInfo.getId();
    }

    @Override
    public PageResponse queryReservationList(PileReservationDTO dto) {
        int pageNo = dto.getPageNo() == null ? Constants.one : dto.getPageNo();
        int pageSize = dto.getPageSize() == null ? 10 : dto.getPageSize();
        PageHelper.startPage(pageNo, pageSize);
        List<PileReservationInfo> list = this.getReservationsByMemberIdAndPileSn(dto.getMemberId(), dto.getPileSn());
        PageInfo<PileReservationInfo> pageInfo = new PageInfo<>(list);

        PageResponse pageResponse = new PageResponse();
        pageResponse.setPageNum(pageInfo.getPageNum());
        pageResponse.setPageSize(pageInfo.getPageSize());
        pageResponse.setPages(pageInfo.getPages());
        pageResponse.setTotal(pageInfo.getTotal());

        List<PileReservedVO> resultList = Lists.newArrayList();
        for (PileReservationInfo reservedInfo : pageInfo.getList()) {
            resultList.add(
                    PileReservedVO.builder()
                            .reservedId(reservedInfo.getId() + "")
                            .pileSn(reservedInfo.getPileSn())
                            .startTime(reservedInfo.getStartTime().toString())
                            .endTime(reservedInfo.getEndTime().toString())
                            .freq(reservedInfo.getFreq())
                            .status(reservedInfo.getStatus())
                            .build()
            );
        }
        pageResponse.setList(resultList);
        return pageResponse;
    }

    /**
     * 修改预约状态
     * @param dto
     */
    @Override
    public void updateReservationStatus(PileReservationDTO dto) {
        if (StringUtils.equals(dto.getStatus(), Constants.ZERO)) {
            // 停用
            this.deactivateReserved(dto);
        } else if (StringUtils.equals(dto.getStatus(), Constants.ONE)) {
            // 启用
            this.activateReserved(dto);
        }
    }

    /**
     * 修改预约充电信息
     * @param dto
     */
    @Override
    public void updateReservation(PileReservationDTO dto) {
        PileReservationInfo pileReservationInfo = pileReservationInfoMapper.selectByPrimaryKey(Integer.valueOf(dto.getReservedId()));
        if (pileReservationInfo == null) {
            return;
        }
        if (!StringUtils.equals(dto.getMemberId(), pileReservationInfo.getMemberId())) {
            return;
        }

        if (StringUtils.isNotBlank(dto.getStartTime())) {
            pileReservationInfo.setStartTime(Time.valueOf(dto.getStartTime()));
        }
        if (StringUtils.isNotBlank(dto.getEndTime())) {
            pileReservationInfo.setEndTime(Time.valueOf(dto.getEndTime()));
        }
        if (StringUtils.isNotBlank(dto.getStatus())) {
            pileReservationInfo.setStatus(dto.getStatus());
        }
        this.insertOrUpdateSelective(pileReservationInfo);
    }

    /**
     * 个人桩停止充电
     * @param dto
     */
    @Override
    public void personPileStopCharging(PersonPileStopChargingDTO dto) {
        // 查询个人桩信息

        // 发送请求的用户有没有权限停止充电


    }
}

