package cn.iocoder.yudao.module.asset.service.vehicleregistration;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.asset.controller.admin.vehicleregistration.vo.VehicleLicenseRecognizeRespVO;
import cn.iocoder.yudao.module.asset.controller.admin.vehicleregistration.vo.VehicleRegistrationPageReqVO;
import cn.iocoder.yudao.module.asset.controller.admin.vehicleregistration.vo.VehicleRegistrationSaveReqVO;
import cn.iocoder.yudao.module.asset.convert.vehicleregistration.VehicleRegistrationConvert;
import cn.iocoder.yudao.module.asset.dal.dataobject.vehicle.VehicleBaseDO;
import cn.iocoder.yudao.module.asset.dal.dataobject.vehicleregistration.VehicleRegistrationDO;
import cn.iocoder.yudao.module.asset.dal.mysql.vehicle.VehicleBaseMapper;
import cn.iocoder.yudao.module.asset.dal.mysql.vehicleregistration.VehicleRegistrationMapper;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.ocr.api.OcrApi;
import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseReqDTO;
import cn.iocoder.yudao.module.ocr.api.dto.VehicleLicenseRespDTO;
import cn.hutool.core.codec.Base64;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import jakarta.annotation.Resource;
import java.math.BigDecimal;

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

/**
 * 车辆上牌记录 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
public class VehicleRegistrationServiceImpl implements VehicleRegistrationService {

    @Resource
    private VehicleRegistrationMapper vehicleRegistrationMapper;

    @Resource
    private VehicleBaseMapper vehicleBaseMapper;

    @Resource
    private OcrApi ocrApi;

    @Override
    public VehicleLicenseRecognizeRespVO recognizeVehicleLicense(byte[] imageData) {
        long startTime = System.currentTimeMillis();

        // Base64 编码图片数据
        String imageDataBase64 = Base64.encode(imageData);

        // 调用 OCR API 识别
        VehicleLicenseReqDTO reqDTO = new VehicleLicenseReqDTO();
        reqDTO.setImageData(imageDataBase64);
        CommonResult<VehicleLicenseRespDTO> ocrResult = ocrApi.recognizeVehicleLicense(reqDTO);

        long costTime = System.currentTimeMillis() - startTime;

        // 检查调用结果
        if (ocrResult == null || !ocrResult.isSuccess() || ocrResult.getData() == null) {
            log.error("[recognizeVehicleLicense][OCR识别失败，结果：{}]", ocrResult);
            throw exception(new ErrorCode(500, "OCR识别失败"));
        }

        VehicleLicenseRespDTO ocrData = ocrResult.getData();
        log.info("[recognizeVehicleLicense][OCR识别完成，耗时：{}ms，VIN：{}，车牌号：{}]",
                costTime, ocrData.getVin(), ocrData.getPlateNo());

        // 转换为响应 VO
        VehicleLicenseRecognizeRespVO respVO = new VehicleLicenseRecognizeRespVO();
        BeanUtil.copyProperties(ocrData, respVO);
        respVO.setOcrProvider("baidu");
        respVO.setOcrCostTime((int) costTime);

        // 根据 VIN 查找车辆
        if (StrUtil.isNotBlank(ocrData.getVin())) {
            VehicleBaseDO vehicle = vehicleBaseMapper.selectOne(new LambdaQueryWrapper<VehicleBaseDO>()
                    .eq(VehicleBaseDO::getVin, ocrData.getVin())
                    .last("LIMIT 1"));

            if (vehicle != null) {
                respVO.setVehicleId(vehicle.getId());
                respVO.setVehicleModelId(vehicle.getVehicleModelId());
                respVO.setMatchMethod("exact");
                respVO.setMatchConfidence(new BigDecimal("100.00"));
                log.info("[recognizeVehicleLicense][找到匹配车辆，车辆ID：{}]", vehicle.getId());
            } else {
                respVO.setMatchMethod("none");
                respVO.setMatchConfidence(BigDecimal.ZERO);
                log.warn("[recognizeVehicleLicense][未找到匹配车辆，VIN：{}]", ocrData.getVin());
            }
        }

        return respVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createVehicleRegistration(VehicleRegistrationSaveReqVO createReqVO) {
        // 通过 VIN 验证车辆是否存在
        VehicleBaseDO vehicle = validateVehicleExistsByVin(createReqVO.getVin());

        // 插入
        VehicleRegistrationDO registration = VehicleRegistrationConvert.INSTANCE.convert(createReqVO);
        registration.setVehicleId(vehicle.getId());
        registration.setStatus(0); // 待确认
        vehicleRegistrationMapper.insert(registration);

        log.info("[createVehicleRegistration][创建上牌记录成功，ID：{}，车辆ID：{}，车牌号：{}]",
                registration.getId(), registration.getVehicleId(), registration.getPlateNo());

        return registration.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateVehicleRegistration(VehicleRegistrationSaveReqVO updateReqVO) {
        // 校验存在
        validateVehicleRegistrationExists(updateReqVO.getId());

        // 通过 VIN 验证车辆是否存在
        if (StrUtil.isNotBlank(updateReqVO.getVin())) {
            VehicleBaseDO vehicle = validateVehicleExistsByVin(updateReqVO.getVin());
            updateReqVO.setVehicleId(vehicle.getId());
        }

        // 更新
        VehicleRegistrationDO updateObj = VehicleRegistrationConvert.INSTANCE.convert(updateReqVO);
        vehicleRegistrationMapper.updateById(updateObj);

        log.info("[updateVehicleRegistration][更新上牌记录成功，ID：{}]", updateReqVO.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteVehicleRegistration(Long id) {
        // 校验存在
        validateVehicleRegistrationExists(id);

        // 删除
        vehicleRegistrationMapper.deleteById(id);

        log.info("[deleteVehicleRegistration][删除上牌记录成功，ID：{}]", id);
    }

    @Override
    public VehicleRegistrationDO getVehicleRegistration(Long id) {
        return vehicleRegistrationMapper.selectById(id);
    }

    @Override
    public PageResult<VehicleRegistrationDO> getVehicleRegistrationPage(VehicleRegistrationPageReqVO pageReqVO) {
        return vehicleRegistrationMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmRegistration(Long id) {
        // 获取上牌记录
        VehicleRegistrationDO registration = validateVehicleRegistrationExists(id);

        // 验证状态
        if (registration.getStatus() != 0) {
            throw exception(new ErrorCode(400, "上牌记录已确认或已作废"));
        }

        // 更新车辆信息
        VehicleBaseDO vehicle = validateVehicleExists(registration.getVehicleId());
        VehicleBaseDO updateVehicle = new VehicleBaseDO();
        updateVehicle.setId(vehicle.getId());
        updateVehicle.setPlateNo(registration.getPlateNo());
        updateVehicle.setVin(registration.getVin());
        updateVehicle.setEngineNo(registration.getEngineNo());
        updateVehicle.setRegisterDate(registration.getRegisterDate());
        updateVehicle.setScrapDate(registration.getScrapDate());
        if (StrUtil.isNotBlank(registration.getInspectionRecord())) {
            updateVehicle.setInspectExpire(registration.getInspectionRecord());
        }
        if (registration.getVehicleModelId() != null) {
            updateVehicle.setVehicleModelId(registration.getVehicleModelId());
        }

        vehicleBaseMapper.updateById(updateVehicle);

        // 更新上牌记录状态为已确认
        VehicleRegistrationDO updateRegistration = new VehicleRegistrationDO();
        updateRegistration.setId(id);
        updateRegistration.setStatus(1);
        vehicleRegistrationMapper.updateById(updateRegistration);

        log.info("[confirmRegistration][确认上牌记录成功，ID：{}，车辆ID：{}]", id, vehicle.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void voidRegistration(Long id) {
        VehicleRegistrationDO registration = validateVehicleRegistrationExists(id);
        if (registration.getStatus() != 0) {
            throw exception(new ErrorCode(400, "上牌记录已确认或已作废"));
        }
        VehicleRegistrationDO updateObj = new VehicleRegistrationDO();
        updateObj.setId(id);
        updateObj.setStatus(2); // 2=已作废
        vehicleRegistrationMapper.updateById(updateObj);
        log.info("[voidRegistration][作废上牌记录成功，ID：{}]", id);
    }

    // ==================== 私有方法 ====================

    private VehicleRegistrationDO validateVehicleRegistrationExists(Long id) {
        VehicleRegistrationDO registration = vehicleRegistrationMapper.selectById(id);
        if (registration == null) {
            throw exception(new ErrorCode(400, "上牌记录不存在"));
        }
        return registration;
    }

    private VehicleBaseDO validateVehicleExists(Long vehicleId) {
        VehicleBaseDO vehicle = vehicleBaseMapper.selectById(vehicleId);
        if (vehicle == null) {
            throw exception(new ErrorCode(400, "车辆不存在，请先录入车辆信息"));
        }
        return vehicle;
    }

    private VehicleBaseDO validateVehicleExistsByVin(String vin) {
        if (StrUtil.isBlank(vin)) {
            throw exception(new ErrorCode(400, "VIN不能为空"));
        }
        VehicleBaseDO vehicle = vehicleBaseMapper.selectOne(new LambdaQueryWrapper<VehicleBaseDO>()
                .eq(VehicleBaseDO::getVin, vin)
                .last("LIMIT 1"));
        if (vehicle == null) {
            throw exception(new ErrorCode(400, "车辆不存在，请先录入车辆信息"));
        }
        return vehicle;
    }

}
