package com.hotwj.platform.config.vehicleBrandModel.controller;

import com.hotwj.platform.config.vehicleBrandModel.domain.bo.HotVehicleBrandModelBo;
import com.hotwj.platform.config.vehicleBrandModel.domain.vo.HotVehicleBrandModelVo;
import com.hotwj.platform.config.vehicleBrandModel.service.IHotVehicleBrandModelService;
import com.hotwj.platform.resourceManagement.vehicleManagement.domain.bo.HotVehicleBo;
import com.hotwj.platform.resourceManagement.vehicleManagement.domain.vo.HotVehicleVo;
import com.hotwj.platform.resourceManagement.vehicleManagement.service.IHotVehicleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 车辆品牌型号库
 *
 * @author shihongwei
 * @date 2026-02-24
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/config/vehicleBrandModel")
@Tag(name = "车辆品牌型号库", description = "车辆品牌型号库管理")
public class HotVehicleBrandModelController extends BaseController {

    private final IHotVehicleBrandModelService hotVehicleBrandModelService;
    private final IHotVehicleService hotVehicleService;
    /**
     * 查询车辆品牌型号库列表
     */
    //@SaCheckPermission("config:vehicleBrandModel:list")
    @GetMapping("/list")
    @Operation(summary = "分页查询车辆品牌型号库列表")
    public TableDataInfo<HotVehicleBrandModelVo> list(HotVehicleBrandModelBo bo, PageQuery pageQuery) {
        return hotVehicleBrandModelService.queryPageList(bo, pageQuery);
    }

    /**
     * 从车辆库中提取品牌型号建议（分页）
     * 规则：
     * 1) 返回不存在于品牌型号库的 vehicleModel，或品牌型号库中该 vehicleModel 的数据缺陷>0
     * 2) 同一 vehicleModel 若有多条车辆数据，选择数据缺陷最少的一条；如缺陷数相同，选择录入时间更早的一条
     * 3) 支持按车辆型号模糊查询
     */
    //@SaCheckPermission("config:vehicleBrandModel:list")
    @GetMapping("/suggestFromVehicles")
    @Operation(summary = "从车辆库提取品牌型号建议（分页）")
    public TableDataInfo<HotVehicleBrandModelVo> suggestFromVehicles(
            @RequestParam(required = false) String brandModel,
            PageQuery pageQuery
    ) {
        List<HotVehicleVo> vehicles = hotVehicleService.queryList(new HotVehicleBo());
        if (vehicles == null) vehicles = Collections.emptyList();
        // 模糊过滤
        final String q = brandModel;
        vehicles = vehicles.stream()
                .filter(v -> v.getBrandModel() != null && !v.getBrandModel().isBlank())
                .filter(v -> q == null || q.isBlank() || v.getBrandModel().toLowerCase().contains(q.toLowerCase()))
                .collect(Collectors.toList());

        // 现有品牌型号库（用于排除已完善的型号，按品牌型号+车辆型号双条件）
        List<HotVehicleBrandModelVo> existing = hotVehicleBrandModelService.queryList(new HotVehicleBrandModelBo());
        Map<String, HotVehicleBrandModelVo> existingByKey = existing.stream()
                .filter(e -> e.getBrandModel() != null && !e.getBrandModel().isBlank())
                .collect(Collectors.toMap(e -> compositeKey(e.getBrandModel(), e.getVehicleModel()), e -> e, (a, b) -> a));

        Set<String> goodKeys = existing.stream()
                .filter(e -> e.getBrandModel() != null && !e.getBrandModel().isBlank())
                .filter(e -> e.getDataMissingCount() == null || e.getDataMissingCount() == 0L)
                .map(e -> compositeKey(e.getBrandModel(), e.getVehicleModel()))
                .collect(Collectors.toSet());

        Set<String> defectiveKeys = existing.stream()
                .filter(e -> e.getBrandModel() != null && !e.getBrandModel().isBlank())
                .filter(e -> e.getDataMissingCount() != null && e.getDataMissingCount() > 0L)
                .map(e -> compositeKey(e.getBrandModel(), e.getVehicleModel()))
                .collect(Collectors.toSet());

        // 按品牌型号+车辆型号分组
        Map<String, List<HotVehicleVo>> byKey = vehicles.stream()
                .collect(Collectors.groupingBy(v -> compositeKey(v.getBrandModel(), v.getVehicleModel())));

        List<HotVehicleBrandModelVo> result = new ArrayList<>();
        for (Map.Entry<String, List<HotVehicleVo>> entry : byKey.entrySet()) {
            String key = entry.getKey();
            boolean include = !goodKeys.contains(key) || defectiveKeys.contains(key);
            if (!include) continue;

            // 选择缺陷最少，若相同取创建时间更早
            HotVehicleVo best = entry.getValue().stream()
                    .sorted((a, b) -> {
                        int da = countDefects(a);
                        int db = countDefects(b);
                        if (da != db) return Integer.compare(da, db);
                        String ia = a.getId();
                        String ib = b.getId();
                        if (ia == null && ib == null) return 0;
                        if (ia == null) return 1;
                        if (ib == null) return -1;
                        return ia.compareTo(ib);
                    })
                    .findFirst().orElse(null);
            if (best == null) continue;

            HotVehicleBrandModelVo vo = new HotVehicleBrandModelVo();
            vo.setVehicleType(best.getVehicleType());
            vo.setBrandModel(best.getBrandModel());
            vo.setBodyColor(best.getColor());
            vo.setPlateColor(best.getPlateColor());
            vo.setFuelType(best.getFuelType());
            vo.setManufacturerName(best.getManufacturerName());
            vo.setEngineDisplacement(best.getEngineDisplacementMl());
            vo.setEnginePowerKw(best.getEnginePowerKw());
            vo.setMotorPowerKw(best.getMotorPowerKw());
            vo.setDriveMotorModel(null);
            vo.setWheelbaseMm(best.getWheelbaseMm());
            vo.setTireCount(best.getTireCount());
            vo.setTireSpec(best.getTireSpec());
            vo.setAxleCount(best.getAxleCount());
            vo.setVehicleModel(best.getVehicleModel());
            vo.setCargoLengthMm(best.getCargoInnerLengthMm());
            vo.setCargoWidthMm(best.getCargoInnerWidthMm());
            vo.setCargoHeightMm(best.getCargoInnerHeightMm());
            vo.setCargoVolume(best.getCargoInnerVolumeM3());
            vo.setTransmission(best.getTransmission());
            vo.setRetarder(best.getRetarder());
            vo.setEmissionStandard(best.getEmissionStandard());
            vo.setBatteryType(best.getBatteryType());
            vo.setInsuredSeatCount(best.getInsuredSeatCount());
            vo.setServiceBrakeType(best.getServiceBrakeType());
            vo.setFrontBrakeType(best.getFrontBrakeType());
            vo.setRearBrakeType(best.getRearBrakeType());
            vo.setAbsSystem(best.getHasAbs());
            vo.setParkingBrakeType(null);
            vo.setAirConditioning(best.getHasAirConditioning());
            vo.setChassisModel(best.getChassisModel());
            vo.setDomesticFlag(best.getDomesticMark());
            vo.setDataMissingCount((long) countDefects(best));
            vo.setId(Long.valueOf(best.getId()));
            result.add(vo);
        }

        // 排序：缺陷少优先，其次创建时间更早（通过existing记录或不考虑）
        result.sort((a, b) -> {
            long da = a.getDataMissingCount() != null ? a.getDataMissingCount() : 0L;
            long db = b.getDataMissingCount() != null ? b.getDataMissingCount() : 0L;
            int cmp = Long.compare(da, db);
            if (cmp != 0) return cmp;
            // 如有现成库的 createTime，可比较；否则保持当前顺序
            return 0;
        });

        // 分页
        int pageNum = Optional.ofNullable(pageQuery.getPageNum()).orElse(PageQuery.DEFAULT_PAGE_NUM);
        int pageSize = Optional.ofNullable(pageQuery.getPageSize()).orElse(PageQuery.DEFAULT_PAGE_SIZE);
        if (pageNum <= 0) pageNum = PageQuery.DEFAULT_PAGE_NUM;
        int total = result.size();
        int fromIndex = Math.min((pageNum - 1) * pageSize, total);
        int toIndex = Math.min(fromIndex + pageSize, total);
        List<HotVehicleBrandModelVo> rows = result.subList(fromIndex, toIndex);
        return new TableDataInfo<>(rows, total);
    }

    private String compositeKey(String brandModel, String vehicleModel) {
        String bm = brandModel == null ? "" : brandModel.trim();
        String vm = vehicleModel == null ? "" : vehicleModel.trim();
        return bm + "##" + vm;
    }

    /**
     * 同步品牌型号库（根据车辆ID自动补全并新增）
     * 仅需传入车辆主键ID，其他信息由系统自动从车辆信息中补全
     */
    //@SaCheckPermission("config:vehicleBrandModel:add")
    @PostMapping("/suggestFromVehicles/sync")
    @Operation(summary = "批量根据车辆ID同步品牌型号到品牌型号库")
    public R<String> syncFromVehicles(@NotEmpty(message = "车辆ID集合不能为空") String vehicleIds) {
        if (vehicleIds == null || vehicleIds.isBlank()) {
            return R.fail("车辆ID集合不能为空");
        }
        List<Long> idList = Arrays.stream(vehicleIds.split(","))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .map(Long::valueOf)
                .collect(Collectors.toList());
        List<HotVehicleBrandModelVo> existing = hotVehicleBrandModelService.queryList(new HotVehicleBrandModelBo());
        Set<String> existingKeys = existing.stream()
                .filter(e -> e.getBrandModel() != null && !e.getBrandModel().isBlank())
                .map(e -> compositeKey(e.getBrandModel(), e.getVehicleModel()))
                .collect(Collectors.toSet());
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (Long vehicleId : idList) {
            try {
                HotVehicleVo v = hotVehicleService.queryById(vehicleId);
                if (v == null) {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、车辆ID ").append(vehicleId).append(" 不存在");
                    continue;
                }
                String key = compositeKey(v.getBrandModel(), v.getVehicleModel());
                if (existingKeys.contains(key)) {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、品牌型号/车辆型号组合已存在：").append(key);
                    continue;
                }
                HotVehicleBrandModelBo bo = new HotVehicleBrandModelBo();
//                bo.setVehicleType(v.getVehicleType());
                bo.setBrandModel(v.getBrandModel());
                bo.setBodyColor(v.getColor());
                bo.setPlateColor(v.getPlateColor());
                bo.setFuelType(v.getFuelType());
                bo.setManufacturerName(v.getManufacturerName());
                bo.setEngineDisplacement(v.getEngineDisplacementMl());
                bo.setEnginePowerKw(v.getEnginePowerKw());
                bo.setMotorPowerKw(v.getMotorPowerKw());
                bo.setWheelbaseMm(v.getWheelbaseMm());
                bo.setTireCount(v.getTireCount());
                bo.setTireSpec(v.getTireSpec());
                bo.setAxleCount(v.getAxleCount());
                bo.setVehicleModel(v.getVehicleModel());
                bo.setCargoLengthMm(v.getCargoInnerLengthMm());
                bo.setCargoWidthMm(v.getCargoInnerWidthMm());
                bo.setCargoHeightMm(v.getCargoInnerHeightMm());
                bo.setCargoVolume(v.getCargoInnerVolumeM3());
                bo.setTransmission(v.getTransmission());
                bo.setRetarder(v.getRetarder());
                bo.setEmissionStandard(v.getEmissionStandard());
                bo.setBatteryType(v.getBatteryType());
                bo.setInsuredSeatCount(v.getInsuredSeatCount());
                bo.setServiceBrakeType(v.getServiceBrakeType());
                bo.setFrontBrakeType(v.getFrontBrakeType());
                bo.setRearBrakeType(v.getRearBrakeType());
                bo.setAbsSystem(v.getHasAbs());
                bo.setAirConditioning(v.getHasAirConditioning());
                bo.setChassisModel(v.getChassisModel());
                bo.setDomesticFlag(v.getDomesticMark());
                bo.setDataMissingCount((long) countDefects(v));
                boolean ok = hotVehicleBrandModelService.insertByBo(bo);
                if (ok) {
                    existingKeys.add(key);
                    successNum++;
                    successMsg.append("<br/>").append(successNum).append("、同步成功：").append(key);
                } else {
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、同步失败：").append(key);
                }
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>").append(failureNum).append("、车辆ID ").append(vehicleId).append(" 同步异常：").append(e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "部分同步失败！共 " + failureNum + " 条，如下：");
        }
        if (successNum > 0) {
            successMsg.insert(0, "同步成功共 " + successNum + " 条，详情：");
        }
        return R.ok(successMsg.toString() + failureMsg.toString());
    }

    private int countDefects(HotVehicleVo v) {
        int cnt = 0;
        cnt += isBlank(v.getVehicleType());
        cnt += isBlank(v.getBrandModel());
        cnt += isBlank(v.getColor());
        cnt += isBlank(v.getPlateColor());
        cnt += isBlank(v.getFuelType());
        cnt += isBlank(v.getManufacturerName());
        cnt += isNull(v.getEngineDisplacementMl());
        cnt += isNull(v.getEnginePowerKw());
        cnt += isNull(v.getMotorPowerKw());
        cnt += isNull(v.getWheelbaseMm());
        cnt += isNull(v.getTireCount());
        cnt += isBlank(v.getTireSpec());
        cnt += isNull(v.getAxleCount());
        cnt += isBlank(v.getVehicleModel());
        cnt += isNull(v.getCargoInnerLengthMm());
        cnt += isNull(v.getCargoInnerWidthMm());
        cnt += isNull(v.getCargoInnerHeightMm());
        cnt += isNull(v.getCargoInnerVolumeM3());
        cnt += isBlank(v.getTransmission());
        cnt += isBlank(v.getRetarder());
        cnt += isBlank(v.getEmissionStandard());
        cnt += isBlank(v.getBatteryType());
        cnt += isNull(v.getInsuredSeatCount());
        cnt += isBlank(v.getServiceBrakeType());
        cnt += isBlank(v.getFrontBrakeType());
        cnt += isBlank(v.getRearBrakeType());
        cnt += (v.getHasAbs() == null ? 1 : 0);
        cnt += (v.getHasAirConditioning() == null ? 1 : 0);
        cnt += isBlank(v.getChassisModel());
        cnt += (v.getDomesticMark() == null ? 1 : 0);
        return cnt;
    }

    private int isBlank(String s) {
        return (s == null || s.isBlank()) ? 1 : 0;
    }

    private int isNull(Object o) {
        return (o == null) ? 1 : 0;
    }

    /**
     * 导出车辆品牌型号库列表
     */
    //@SaCheckPermission("config:vehicleBrandModel:export")
    @Log(title = "车辆品牌型号库", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @Operation(summary = "导出车辆品牌型号库列表")
    public void export(HotVehicleBrandModelBo bo, HttpServletResponse response) {
        List<HotVehicleBrandModelVo> list = hotVehicleBrandModelService.queryList(bo);
        ExcelUtil.exportExcel(list, "车辆品牌型号库", HotVehicleBrandModelVo.class, response);
    }

    /**
     * 获取车辆品牌型号库详细信息
     *
     * @param id 主键
     */
    //@SaCheckPermission("config:vehicleBrandModel:query")
    @GetMapping("/{id}")
    @Operation(summary = "获取车辆品牌型号库详细信息")
    public R<HotVehicleBrandModelVo> getInfo(@NotNull(message = "主键不能为空")
                                             @Parameter(name = "id", description = "主键", required = true, example = "1")
                                             @PathVariable Long id) {
        return R.ok(hotVehicleBrandModelService.queryById(id));
    }

    /**
     * 新增车辆品牌型号库
     */
    //@SaCheckPermission("config:vehicleBrandModel:add")
    @Log(title = "车辆品牌型号库", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    @Operation(summary = "新增车辆品牌型号库")
    public R<Void> add(@Validated(AddGroup.class) @RequestBody HotVehicleBrandModelBo bo) {
        return toAjax(hotVehicleBrandModelService.insertByBo(bo));
    }

    /**
     * 修改车辆品牌型号库
     */
    //@SaCheckPermission("config:vehicleBrandModel:edit")
    @Log(title = "车辆品牌型号库", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    @Operation(summary = "修改车辆品牌型号库")
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody HotVehicleBrandModelBo bo) {
        return toAjax(hotVehicleBrandModelService.updateByBo(bo));
    }

    /**
     * 删除车辆品牌型号库
     *
     * @param ids 主键串
     */
    //@SaCheckPermission("config:vehicleBrandModel:remove")
    @Log(title = "车辆品牌型号库", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @Operation(summary = "删除车辆品牌型号库")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @Parameter(name = "ids", description = "主键串", required = true, example = "1,2,3")
                          @PathVariable Long[] ids) {
        return toAjax(hotVehicleBrandModelService.deleteWithValidByIds(List.of(ids), true));
    }
}
