package com.zt.plat.module.base.service.materialhasproperties;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zt.plat.framework.test.core.ut.BaseDbUnitTest;
import com.zt.plat.module.base.controller.admin.materialhasproperties.vo.MaterialHasPropertiesBatchItemReqVO;
import com.zt.plat.module.base.controller.admin.materialhasproperties.vo.MaterialHasPropertiesBatchSaveReqVO;
import com.zt.plat.module.base.controller.admin.materialhasproperties.vo.MaterialHasPropertiesBatchSaveRespVO;
import com.zt.plat.module.base.controller.admin.materialhasproperties.vo.RowValidationErrorVO;
import com.zt.plat.module.base.dal.dao.materialhasproperties.MaterialHasPropertiesMapper;
import com.zt.plat.module.base.dal.dataobject.materialhasproperties.MaterialHasPropertiesDO;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.zt.plat.framework.test.core.util.RandomUtils.randomLongId;
import static org.assertj.core.api.Assertions.assertThat;

/**
 * {@link MaterialHasPropertiesServiceImpl} 单元测试
 */
@Import(MaterialHasPropertiesServiceImpl.class)
class MaterialHasPropertiesServiceImplTest extends BaseDbUnitTest {

    @Resource
    private MaterialHasPropertiesServiceImpl materialHasPropertiesService;

    @Resource
    private MaterialHasPropertiesMapper materialHasPropertiesMapper;

    private MaterialHasPropertiesDO insertRelation(Long infoId, Long propId, String value, Long sort) {
        MaterialHasPropertiesDO entity = MaterialHasPropertiesDO.builder()
                .id(randomLongId())
                .infomationId(infoId)
                .propertiesId(propId)
                .value(value)
                .sort(sort)
                .build();
        materialHasPropertiesMapper.insert(entity);
        return entity;
    }

    @Test
    void batchSave_shouldReplaceAndDedup() {
        Long infoId = 1001L;
        // 旧数据：同一个物料下的旧记录 + 其他物料记录
        insertRelation(infoId, 9L, "old", 1L);
        insertRelation(2002L, 99L, "other", 1L);

        MaterialHasPropertiesBatchItemReqVO item1 = new MaterialHasPropertiesBatchItemReqVO();
        item1.setPropertiesId(9L);
        item1.setValue("new-val");
        item1.setIsKey(1);

        MaterialHasPropertiesBatchItemReqVO item2 = new MaterialHasPropertiesBatchItemReqVO();
        item2.setPropertiesId(10L);
        item2.setValue("v10");
        item2.setSort(5L);

        // 重复属性，应该被去重跳过
        MaterialHasPropertiesBatchItemReqVO itemDuplicate = new MaterialHasPropertiesBatchItemReqVO();
        itemDuplicate.setPropertiesId(9L);
        itemDuplicate.setValue("dup");

        MaterialHasPropertiesBatchSaveReqVO req = new MaterialHasPropertiesBatchSaveReqVO();
        req.setInfomationId(infoId);
        req.setProperties(CollUtil.newArrayList(item1, item2, itemDuplicate));

        MaterialHasPropertiesBatchSaveRespVO resp = materialHasPropertiesService.batchSave(req, null);

        assertThat(resp.getRowErrors()).isEmpty();

        List<MaterialHasPropertiesDO> result = materialHasPropertiesMapper.selectList();
        // 只应保留当前物料的新两条 + 另一物料的 1 条
        assertThat(result).hasSize(3);

        List<MaterialHasPropertiesDO> current = result.stream()
                .filter(item -> infoId.equals(item.getInfomationId()))
                .toList();
        assertThat(current).hasSize(2);

        Set<Long> propIds = current.stream().map(MaterialHasPropertiesDO::getPropertiesId).collect(Collectors.toSet());
        assertThat(propIds).containsExactlyInAnyOrder(9L, 10L);

        MaterialHasPropertiesDO updated = current.stream()
                .filter(item -> item.getPropertiesId().equals(9L)).findFirst().orElseThrow();
        assertThat(updated.getValue()).isEqualTo("new-val");
    }

    @Test
    void batchSave_missingInfoId_shouldReturnErrorAndSkipInsert() {
        MaterialHasPropertiesBatchSaveReqVO req = new MaterialHasPropertiesBatchSaveReqVO();
        MaterialHasPropertiesBatchSaveRespVO resp = materialHasPropertiesService.batchSave(req, null);

        assertThat(resp.getRowErrors()).hasSize(1);
        RowValidationErrorVO error = resp.getRowErrors().get(0);
        assertThat(error.getMessage()).contains("物料信息 ID 不能为空");

        assertThat(materialHasPropertiesMapper.selectList()).isEmpty();
    }

    @Test
    void batchSave_emptyList_shouldDeleteExisting() {
        Long infoId = 3003L;
        insertRelation(infoId, 77L, "keep", 1L);

        MaterialHasPropertiesBatchSaveReqVO req = new MaterialHasPropertiesBatchSaveReqVO();
        req.setInfomationId(infoId);
        req.setProperties(List.of());

        MaterialHasPropertiesBatchSaveRespVO resp = materialHasPropertiesService.batchSave(req, null);
        assertThat(resp.getRowErrors()).isEmpty();

        List<MaterialHasPropertiesDO> current = materialHasPropertiesMapper.selectList(new QueryWrapper<MaterialHasPropertiesDO>()
            .eq("INF_ID", infoId));
        assertThat(current).isEmpty();
    }

    @Test
    void batchSave_blankValue_shouldCollectRowError() {
        Long infoId = 4004L;

        MaterialHasPropertiesBatchItemReqVO item = new MaterialHasPropertiesBatchItemReqVO();
        item.setPropertiesId(55L);
        item.setValue("   ");

        MaterialHasPropertiesBatchSaveReqVO req = new MaterialHasPropertiesBatchSaveReqVO();
        req.setInfomationId(infoId);
        req.setProperties(List.of(item));

        MaterialHasPropertiesBatchSaveRespVO resp = materialHasPropertiesService.batchSave(req, null);

        assertThat(resp.getRowErrors()).hasSize(1);
        RowValidationErrorVO error = resp.getRowErrors().get(0);
        assertThat(error.getRowIndex()).isEqualTo(1);
        assertThat(error.getMessage()).contains("属性值不能为空");

        List<MaterialHasPropertiesDO> saved = materialHasPropertiesMapper.selectList(new QueryWrapper<MaterialHasPropertiesDO>()
            .eq("INF_ID", infoId));
        assertThat(saved).isEmpty();
    }
}
