package com.xly.erp.module.mod.mapper;

import com.xly.erp.module.mod.entity.Module;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;

import java.time.LocalDateTime;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("test")
class ModuleMapperIT {

    @Autowired
    private ModuleMapper moduleMapper;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @BeforeEach
    @AfterEach
    void cleanup() {
        jdbcTemplate.update("DELETE FROM tModule WHERE sProcedureName LIKE 'sp_test_%'");
    }

    @Test
    void insertAndSelectById_persistsAllStandardCols() {
        Module m = newModule("sp_test_insert", "插入用例", null);
        int rows = moduleMapper.insert(m);
        assertThat(rows).isEqualTo(1);
        assertThat(m.getIIncrement()).isNotNull();

        Module loaded = moduleMapper.selectById(m.getIIncrement());
        assertThat(loaded.getSProcedureName()).isEqualTo("sp_test_insert");
        assertThat(loaded.getSBrandsId()).isEqualTo("XLY");
        assertThat(loaded.getSSubsidiaryId()).isEqualTo("XLY");
        assertThat(loaded.getSDisplayType()).isEqualTo("手机端");
        assertThat(loaded.getSModuleNameZh()).isEqualTo("插入用例");
        assertThat(loaded.getBDeleted()).isFalse();
        assertThat(loaded.getBShowPermission()).isFalse();
    }

    @Test
    void existsActiveById_trueForAlive_falseForDeleted() {
        Module alive = newModule("sp_test_alive", "活的", null);
        moduleMapper.insert(alive);

        Module dead = newModule("sp_test_dead", "死的", null);
        dead.setBDeleted(true);
        moduleMapper.insert(dead);

        assertThat(moduleMapper.existsActiveById(alive.getIIncrement())).isTrue();
        assertThat(moduleMapper.existsActiveById(dead.getIIncrement())).isFalse();
        assertThat(moduleMapper.existsActiveById(99999999)).isFalse();
    }

    @Test
    void selectParentIdById_returnsNullForRootOrMissing_andValueForChild() {
        Module root = newModule("sp_test_root", "根", null);
        moduleMapper.insert(root);

        Module child = newModule("sp_test_child", "子", root.getIIncrement());
        moduleMapper.insert(child);

        Module deleted = newModule("sp_test_del", "删", root.getIIncrement());
        deleted.setBDeleted(true);
        moduleMapper.insert(deleted);

        assertThat(moduleMapper.selectParentIdById(root.getIIncrement())).isNull();
        assertThat(moduleMapper.selectParentIdById(child.getIIncrement())).isEqualTo(root.getIIncrement());
        assertThat(moduleMapper.selectParentIdById(deleted.getIIncrement())).isNull();
        assertThat(moduleMapper.selectParentIdById(99999998)).isNull();
    }

    @Test
    void hasActiveChildren_trueIfChildAliveExists_falseOtherwise() {
        Module root = newModule("sp_test_hac_root", "根", null);
        moduleMapper.insert(root);

        Module child1 = newModule("sp_test_hac_alive", "存活子", root.getIIncrement());
        moduleMapper.insert(child1);

        Module child2 = newModule("sp_test_hac_dead", "已删子", root.getIIncrement());
        child2.setBDeleted(true);
        moduleMapper.insert(child2);

        assertThat(moduleMapper.hasActiveChildren(root.getIIncrement())).isTrue();
        assertThat(moduleMapper.hasActiveChildren(99999996)).isFalse();

        jdbcTemplate.update("UPDATE tModule SET bDeleted = 1 WHERE iIncrement = ?", child1.getIIncrement());
        assertThat(moduleMapper.hasActiveChildren(root.getIIncrement())).isFalse();
    }

    @Test
    void selectActiveByKeyword_filtersAndOrders() {
        Module a = newModule("sp_test_kw_a", "系统-A", null); a.setISortOrder(1); moduleMapper.insert(a);
        Module b = newModule("sp_test_kw_b", "系统-B", null); b.setISortOrder(0); moduleMapper.insert(b);
        Module c = newModule("sp_test_kw_c", "用户", null); c.setISortOrder(2); moduleMapper.insert(c);
        Module d = newModule("sp_test_kw_d", "系统-D", null); d.setISortOrder(3); d.setBDeleted(true); moduleMapper.insert(d);
        Module e = newModule("sp_test_kw_e", "测试", null); e.setISortOrder(4); moduleMapper.insert(e);

        java.util.List<String> namesByEmpty = moduleMapper.selectActiveByKeyword("").stream()
                .filter(m -> m.getSProcedureName() == null && m.getSModuleNameZh().matches("系统-[ABDE]|用户|测试"))
                .map(Module::getSModuleNameZh).toList();
        // 只取本测试用例插入的 4 行（用 sProcedureName 与名字过滤会丢字段，改为按 iIncrement 集合判定）
        java.util.Set<Integer> insertedIds = java.util.Set.of(
                a.getIIncrement(), b.getIIncrement(), c.getIIncrement(), e.getIIncrement());
        java.util.List<Module> empty = moduleMapper.selectActiveByKeyword("").stream()
                .filter(m -> insertedIds.contains(m.getIIncrement())).toList();
        assertThat(empty).extracting(Module::getIIncrement)
                .containsExactly(b.getIIncrement(), a.getIIncrement(), c.getIIncrement(), e.getIIncrement());

        java.util.List<Module> sys = moduleMapper.selectActiveByKeyword("系统").stream()
                .filter(m -> insertedIds.contains(m.getIIncrement())).toList();
        assertThat(sys).extracting(Module::getIIncrement)
                .containsExactly(b.getIIncrement(), a.getIIncrement());

        assertThat(moduleMapper.selectActiveByKeyword("不存在XYZ-zzz")).isEmpty();
    }

    private Module newModule(String procedureName, String nameZh, Integer parentId) {
        Module m = new Module();
        m.setSBrandsId("XLY");
        m.setSSubsidiaryId("XLY");
        m.setTCreateDate(LocalDateTime.now());
        m.setSDisplayType("手机端");
        m.setSProcedureName(procedureName);
        m.setSModuleType("业务模块");
        m.setSManageDeptEn("IT");
        m.setBShowPermission(false);
        m.setSModuleNameZh(nameZh);
        m.setIParentId(parentId);
        m.setISortOrder(0);
        m.setSCreatedBy("STUB_ADMIN");
        m.setBDeleted(false);
        return m;
    }
}
