package com.pangu.integration;

import com.pangu.common.core.page.TableDataInfo;
import com.pangu.member.domain.dto.MemberDTO;
import com.pangu.member.domain.entity.Member;
import com.pangu.member.domain.vo.MemberVO;
import com.pangu.member.service.IMemberService;
import com.pangu.school.domain.dto.SchoolQueryDTO;
import com.pangu.school.domain.vo.SchoolTreeVO;
import com.pangu.school.domain.vo.SchoolVO;
import com.pangu.school.service.ISchoolService;
import com.pangu.student.domain.dto.StudentDTO;
import com.pangu.student.domain.vo.StudentVO;
import com.pangu.student.service.IStudentService;
import com.pangu.application.domain.dto.ApplicationDTO;
import com.pangu.application.domain.vo.ApplicationVO;
import com.pangu.application.service.IApplicationService;
import com.pangu.base.service.IRegionService;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 模块集成测试类
 * 测试跨模块功能和业务流程
 * 
 * @author 湖北新华业务中台研发团队
 */
@SpringBootTest
@Transactional
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ModuleIntegrationTest {

    @Autowired
    private ISchoolService schoolService;

    @Autowired
    private IMemberService memberService;

    @Autowired
    private IStudentService studentService;

    @Autowired
    private IApplicationService applicationService;

    @Autowired
    private IRegionService regionService;

    // ========== 学校-学生集成测试 ==========

    /**
     * 测试学校树查询并筛选学生
     */
    @Test
    @Order(1)
    public void testSchoolTreeAndStudentFilter() {
        // 1. 获取学校树
        List<SchoolTreeVO> tree = schoolService.selectSchoolTree(111L);
        assertNotNull(tree);
        assertTrue(tree.size() > 0);

        // 2. 根据学校ID筛选学生
        SchoolTreeVO school = tree.get(0);
        StudentDTO query = new StudentDTO();
        query.setSchoolId(school.getId());
        query.setPageNum(1);
        query.setPageSize(10);

        TableDataInfo result = studentService.selectStudentList(query);
        assertNotNull(result);
    }

    /**
     * 测试学校年级班级筛选学生
     */
    @Test
    @Order(2)
    public void testSchoolGradeClassFilter() {
        // 按年级筛选
        StudentDTO gradeQuery = new StudentDTO();
        gradeQuery.setSchoolGradeId(1L);
        gradeQuery.setPageNum(1);
        gradeQuery.setPageSize(10);

        TableDataInfo gradeResult = studentService.selectStudentList(gradeQuery);
        assertNotNull(gradeResult);

        // 按班级筛选
        StudentDTO classQuery = new StudentDTO();
        classQuery.setSchoolClassId(1L);
        classQuery.setPageNum(1);
        classQuery.setPageSize(10);

        TableDataInfo classResult = studentService.selectStudentList(classQuery);
        assertNotNull(classResult);
    }

    // ========== 会员-学生集成测试 ==========

    /**
     * 测试会员绑定学生完整流程
     */
    @Test
    @Order(3)
    public void testMemberStudentBindingFlow() {
        // 1. 创建家长会员
        MemberDTO memberDTO = new MemberDTO();
        memberDTO.setPhone("13811111111");
        memberDTO.setNickname("集成测试家长");
        memberDTO.setIdentityType("1");
        int memberResult = memberService.insertMember(memberDTO);
        assertEquals(1, memberResult);

        // 2. 获取会员ID
        Member member = memberService.getMemberByPhone("13811111111");
        assertNotNull(member);
        Long memberId = member.getMemberId();

        // 3. 创建学生
        StudentDTO studentDTO = new StudentDTO();
        studentDTO.setStudentName("集成测试学生");
        studentDTO.setStudentNo("INT_TEST_001");
        studentDTO.setGender("1");
        studentDTO.setRegionId(111L);
        studentDTO.setSchoolId(1L);
        studentDTO.setSchoolGradeId(1L);
        studentDTO.setSchoolClassId(1L);
        int studentResult = studentService.insertStudent(studentDTO);
        assertEquals(1, studentResult);

        // 4. 查询学生获取ID
        StudentDTO query = new StudentDTO();
        query.setStudentNo("INT_TEST_001");
        query.setPageNum(1);
        query.setPageSize(10);
        TableDataInfo queryResult = studentService.selectStudentList(query);
        @SuppressWarnings("unchecked")
        List<StudentVO> students = (List<StudentVO>) queryResult.getRows();
        Long studentId = students.get(0).getStudentId();

        // 5. 绑定学生到会员
        int bindResult = memberService.bindStudent(memberId, studentId);
        assertEquals(1, bindResult);

        // 6. 验证绑定关系
        MemberVO memberVO = memberService.getMemberById(memberId);
        assertNotNull(memberVO);
        assertNotNull(memberVO.getStudents());
        assertTrue(memberVO.getStudents().size() > 0);

        // 7. 验证学生的会员绑定
        List<StudentVO> boundStudents = studentService.selectStudentVOsByMemberId(memberId);
        assertNotNull(boundStudents);
        assertTrue(boundStudents.size() > 0);
    }

    /**
     * 测试教师只能绑定本校学生
     */
    @Test
    @Order(4)
    public void testTeacherBindStudentRestriction() {
        // 1. 创建教师会员（学校ID=1）
        MemberDTO teacherDTO = new MemberDTO();
        teacherDTO.setPhone("13822222222");
        teacherDTO.setNickname("集成测试教师");
        teacherDTO.setIdentityType("2");
        teacherDTO.setRegionId(111L);
        teacherDTO.setSchoolId(1L);
        teacherDTO.setSchoolGradeId(1L);
        teacherDTO.setSchoolClassId(1L);
        memberService.insertMember(teacherDTO);

        Member teacher = memberService.getMemberByPhone("13822222222");
        assertNotNull(teacher);

        // 2. 创建本校学生
        StudentDTO studentDTO = new StudentDTO();
        studentDTO.setStudentName("本校学生");
        studentDTO.setStudentNo("SAME_SCHOOL_001");
        studentDTO.setGender("1");
        studentDTO.setRegionId(111L);
        studentDTO.setSchoolId(1L); // 同一学校
        studentDTO.setSchoolGradeId(1L);
        studentDTO.setSchoolClassId(1L);
        studentService.insertStudent(studentDTO);

        // 3. 获取学生ID
        StudentDTO query = new StudentDTO();
        query.setStudentNo("SAME_SCHOOL_001");
        query.setPageNum(1);
        query.setPageSize(10);
        TableDataInfo result = studentService.selectStudentList(query);
        @SuppressWarnings("unchecked")
        List<StudentVO> students = (List<StudentVO>) result.getRows();
        Long studentId = students.get(0).getStudentId();

        // 4. 验证学生在教师学校
        boolean inSchool = studentService.isStudentInSchool(studentId, teacher.getSchoolId());
        assertTrue(inSchool);

        // 5. 绑定应该成功
        int bindResult = memberService.bindStudent(teacher.getMemberId(), studentId);
        assertEquals(1, bindResult);
    }

    /**
     * 测试解绑学生后可以删除会员
     */
    @Test
    @Order(5)
    public void testUnbindThenDeleteMember() {
        // 1. 创建会员
        MemberDTO memberDTO = new MemberDTO();
        memberDTO.setPhone("13833333333");
        memberDTO.setNickname("待删除会员");
        memberDTO.setIdentityType("1");
        memberService.insertMember(memberDTO);

        Member member = memberService.getMemberByPhone("13833333333");
        Long memberId = member.getMemberId();

        // 2. 创建并绑定学生
        StudentDTO studentDTO = new StudentDTO();
        studentDTO.setStudentName("待解绑学生");
        studentDTO.setStudentNo("UNBIND_DELETE_001");
        studentDTO.setGender("1");
        studentDTO.setRegionId(111L);
        studentDTO.setSchoolId(1L);
        studentDTO.setSchoolGradeId(1L);
        studentDTO.setSchoolClassId(1L);
        studentDTO.setMemberId(memberId);
        studentService.insertStudent(studentDTO);

        // 3. 验证有绑定学生，不能删除
        assertFalse(memberService.checkCanDelete(memberId));

        // 4. 获取学生ID并解绑
        StudentDTO query = new StudentDTO();
        query.setStudentNo("UNBIND_DELETE_001");
        query.setPageNum(1);
        query.setPageSize(10);
        TableDataInfo result = studentService.selectStudentList(query);
        @SuppressWarnings("unchecked")
        List<StudentVO> students = (List<StudentVO>) result.getRows();
        Long studentId = students.get(0).getStudentId();

        memberService.unbindStudent(memberId, studentId);

        // 5. 验证解绑后可以删除
        assertTrue(memberService.checkCanDelete(memberId));

        // 6. 删除会员
        int deleteResult = memberService.deleteMember(memberId);
        assertEquals(1, deleteResult);
    }

    // ========== 区域-学校-学生链路测试 ==========

    /**
     * 测试区域路径查询功能
     */
    @Test
    @Order(6)
    public void testRegionPathQuery() {
        // 测试区域路径查询
        Long regionId = regionService.getRegionIdByPath("湖北省-武汉市-武昌区");
        // 如果测试数据存在该区域，应该返回ID
        // 否则返回null
        // 这里只验证方法不报错
        assertDoesNotThrow(() -> regionService.getRegionIdByPath("湖北省-武汉市-武昌区"));
    }

    /**
     * 测试学校名称查询功能
     */
    @Test
    @Order(7)
    public void testSchoolNameQuery() {
        // 测试按名称和区域查询学校
        Long schoolId = schoolService.getSchoolIdByName("武汉市第一中学", 111L);
        // 验证方法不报错
        assertDoesNotThrow(() -> schoolService.getSchoolIdByName("武汉市第一中学", 111L));
    }

    // ========== 应用管理集成测试 ==========

    /**
     * 测试应用完整生命周期
     */
    @Test
    @Order(8)
    public void testApplicationLifecycle() {
        // 1. 创建应用
        ApplicationDTO createDTO = new ApplicationDTO();
        createDTO.setAppName("集成测试应用");
        createDTO.setContactPerson("测试人员");
        createDTO.setContactPhone("13800138000");
        createDTO.setApiIds(Arrays.asList(1L, 2L, 3L));

        ApplicationVO created = applicationService.insertApplication(createDTO);
        assertNotNull(created);
        assertNotNull(created.getAppCode());
        assertNotNull(created.getAppSecret());

        Long appId = created.getAppId();

        // 2. 查询应用
        ApplicationVO queried = applicationService.getApplicationById(appId);
        assertNotNull(queried);
        assertEquals("集成测试应用", queried.getAppName());
        assertEquals(3, queried.getApiList().size());

        // 3. 修改应用
        ApplicationDTO updateDTO = new ApplicationDTO();
        updateDTO.setAppId(appId);
        updateDTO.setAppName("集成测试应用（已修改）");
        updateDTO.setContactPerson("新测试人员");
        updateDTO.setContactPhone("13900139000");
        updateDTO.setApiIds(Arrays.asList(4L, 5L, 6L));

        int updateResult = applicationService.updateApplication(updateDTO);
        assertEquals(1, updateResult);

        // 4. 验证修改
        ApplicationVO updated = applicationService.getApplicationById(appId);
        assertEquals("集成测试应用（已修改）", updated.getAppName());
        assertEquals(3, updated.getApiList().size());

        // 5. 重置密钥
        String oldSecret = updated.getAppSecret();
        String newSecret = applicationService.resetSecret(appId);
        assertNotEquals(oldSecret, newSecret);
        assertEquals(32, newSecret.length());

        // 6. 删除应用
        int deleteResult = applicationService.deleteApplication(appId);
        assertEquals(1, deleteResult);

        // 7. 验证已删除
        ApplicationVO deleted = applicationService.getApplicationById(appId);
        assertNull(deleted);
    }

    // ========== 批量导入相关集成测试 ==========

    /**
     * 测试会员自动创建功能
     */
    @Test
    @Order(9)
    public void testGetOrCreateMemberByPhone() {
        String phone = "13899999999";

        // 1. 第一次调用应该创建会员
        Long memberId1 = memberService.getOrCreateMemberByPhone(phone);
        assertNotNull(memberId1);

        // 2. 第二次调用应该返回同一个会员
        Long memberId2 = memberService.getOrCreateMemberByPhone(phone);
        assertEquals(memberId1, memberId2);

        // 3. 验证会员数据
        Member member = memberService.getMemberByPhone(phone);
        assertNotNull(member);
        assertEquals(phone, member.getPhone());
        assertNotNull(member.getMemberCode());
        assertNotNull(member.getNickname());
    }

    /**
     * 测试学校年级班级查询链路
     */
    @Test
    @Order(10)
    public void testSchoolGradeClassQueryChain() {
        // 1. 按区域查询学校
        SchoolQueryDTO schoolQuery = new SchoolQueryDTO();
        schoolQuery.setRegionId(111L);
        List<SchoolVO> schools = schoolService.selectSchoolList(schoolQuery);
        assertNotNull(schools);

        if (!schools.isEmpty()) {
            Long schoolId = schools.get(0).getSchoolId();

            // 2. 查询学校树获取年级
            List<SchoolTreeVO> tree = schoolService.selectSchoolTree(111L);
            SchoolTreeVO schoolTree = tree.stream()
                    .filter(s -> s.getId().equals(schoolId))
                    .findFirst()
                    .orElse(null);

            if (schoolTree != null && schoolTree.getChildren() != null && !schoolTree.getChildren().isEmpty()) {
                SchoolTreeVO grade = schoolTree.getChildren().get(0);
                Long schoolGradeId = grade.getSchoolGradeId();

                // 3. 验证可以获取年级下的班级
                if (grade.getChildren() != null && !grade.getChildren().isEmpty()) {
                    SchoolTreeVO clazz = grade.getChildren().get(0);
                    Long schoolClassId = clazz.getSchoolClassId();
                    assertNotNull(schoolClassId);
                }
            }
        }
    }

    // ========== 数据权限集成测试 ==========

    /**
     * 测试查询参数中的数据权限字段
     */
    @Test
    @Order(11)
    public void testDataScopeParams() {
        // 测试DTO的params字段
        StudentDTO dto = new StudentDTO();
        assertNotNull(dto.getParams());
        assertTrue(dto.getParams() instanceof java.util.Map);

        MemberDTO memberDTO = new MemberDTO();
        assertNotNull(memberDTO.getParams());

        SchoolQueryDTO schoolDTO = new SchoolQueryDTO();
        assertNotNull(schoolDTO.getParams());
    }

    // ========== 统计查询集成测试 ==========

    /**
     * 测试学校相关统计
     */
    @Test
    @Order(12)
    public void testSchoolStatistics() {
        // 测试学校学生数量统计
        int studentCount = studentService.countBySchoolId(1L);
        assertTrue(studentCount >= 0);

        // 测试年级学生数量统计
        int gradeCount = studentService.countBySchoolGradeId(1L);
        assertTrue(gradeCount >= 0);

        // 测试班级学生数量统计
        int classCount = studentService.countBySchoolClassId(1L);
        assertTrue(classCount >= 0);
    }

    /**
     * 测试会员统计
     */
    @Test
    @Order(13)
    public void testMemberStatistics() {
        // 测试会员绑定学生数量
        int studentCount = studentService.countByMemberId(1L);
        assertTrue(studentCount >= 0);
    }
}
