package cn.iocoder.yudao.module.energy.service.record;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.energy.controller.admin.record.vo.HydrogenRecordImportVO;
import cn.iocoder.yudao.module.energy.controller.admin.record.vo.HydrogenRecordPageReqVO;
import cn.iocoder.yudao.module.energy.controller.admin.record.vo.HydrogenRecordSaveReqVO;
import cn.iocoder.yudao.module.energy.convert.record.HydrogenRecordConvert;
import cn.iocoder.yudao.module.energy.dal.dataobject.record.EnergyHydrogenRecordDO;
import cn.iocoder.yudao.module.energy.dal.mysql.record.EnergyHydrogenRecordMapper;
import cn.iocoder.yudao.module.energy.enums.MatchStatusEnum;
import cn.iocoder.yudao.module.energy.enums.SourceTypeEnum;
import cn.iocoder.yudao.module.energy.event.RecordImportedEvent;
import cn.iocoder.yudao.module.energy.event.RecordMatchedEvent;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.energy.enums.ErrorCodeConstants.*;

@Service
@Validated
@Slf4j
public class HydrogenRecordServiceImpl implements HydrogenRecordService {

    @Resource
    private EnergyHydrogenRecordMapper hydrogenRecordMapper;
    @Resource
    private ApplicationEventPublisher eventPublisher;

    @Override
    public Long createRecord(HydrogenRecordSaveReqVO createReqVO) {
        EnergyHydrogenRecordDO record = HydrogenRecordConvert.INSTANCE.convert(createReqVO);
        record.setSourceType(SourceTypeEnum.WEB.getType());
        record.setMatchStatus(MatchStatusEnum.UNMATCHED.getStatus());
        hydrogenRecordMapper.insert(record);
        return record.getId();
    }

    @Override
    public void updateRecord(HydrogenRecordSaveReqVO updateReqVO) {
        validateRecordExists(updateReqVO.getId());
        EnergyHydrogenRecordDO updateObj = HydrogenRecordConvert.INSTANCE.convert(updateReqVO);
        hydrogenRecordMapper.updateById(updateObj);
    }

    @Override
    public void deleteRecord(Long id) {
        validateRecordExists(id);
        hydrogenRecordMapper.deleteById(id);
    }

    @Override
    public EnergyHydrogenRecordDO getRecord(Long id) {
        return hydrogenRecordMapper.selectById(id);
    }

    @Override
    public PageResult<EnergyHydrogenRecordDO> getRecordPage(HydrogenRecordPageReqVO pageReqVO) {
        return hydrogenRecordMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Integer> importRecords(Long stationId, List<HydrogenRecordImportVO> list, String batchNo) {
        if (list == null || list.isEmpty()) {
            throw exception(HYDROGEN_RECORD_IMPORT_EMPTY);
        }
        int successCount = 0;
        int failCount = 0;
        List<Long> recordIds = new ArrayList<>();
        for (HydrogenRecordImportVO importVO : list) {
            try {
                EnergyHydrogenRecordDO record = EnergyHydrogenRecordDO.builder()
                        .stationId(stationId)
                        .plateNumber(importVO.getPlateNumber())
                        .hydrogenDate(importVO.getHydrogenDate())
                        .hydrogenQuantity(importVO.getHydrogenQuantity())
                        .unitPrice(importVO.getUnitPrice())
                        .amount(importVO.getAmount())
                        .mileage(importVO.getMileage())
                        .sourceType(SourceTypeEnum.EXCEL.getType())
                        .matchStatus(MatchStatusEnum.UNMATCHED.getStatus())
                        .uploadBatchNo(batchNo)
                        .build();
                hydrogenRecordMapper.insert(record);
                recordIds.add(record.getId());
                successCount++;
            } catch (Exception e) {
                log.warn("[importRecords] Failed to import record: {}", importVO, e);
                failCount++;
            }
        }
        // Publish event
        if (!recordIds.isEmpty()) {
            eventPublisher.publishEvent(new RecordImportedEvent(stationId, recordIds, batchNo));
        }
        Map<String, Integer> result = new HashMap<>();
        result.put("success", successCount);
        result.put("fail", failCount);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void matchRecord(Long id, Long vehicleId, Long customerId) {
        EnergyHydrogenRecordDO record = validateRecordExists(id);
        hydrogenRecordMapper.updateById(EnergyHydrogenRecordDO.builder()
                .id(id)
                .vehicleId(vehicleId)
                .customerId(customerId)
                .matchStatus(MatchStatusEnum.MATCHED.getStatus())
                .build());
        // Publish event
        eventPublisher.publishEvent(new RecordMatchedEvent(id, record.getStationId(), vehicleId, customerId, record.getPlateNumber()));
    }

    private EnergyHydrogenRecordDO validateRecordExists(Long id) {
        EnergyHydrogenRecordDO record = hydrogenRecordMapper.selectById(id);
        if (record == null) {
            throw exception(HYDROGEN_RECORD_NOT_EXISTS);
        }
        return record;
    }
}
