package com.pangu.member.service;

import com.pangu.common.core.exception.ServiceException;
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 org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;

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

/**
 * 会员服务测试类
 * @author pangu
 */
@SpringBootTest
@Transactional // 测试完成后回滚
public class MemberServiceTest {

    @Autowired
    private IMemberService memberService;

    /**
     * 测试新增家长会员
     */
    @Test
    public void testInsertParentMember() {
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000001");
        dto.setNickname("测试家长");
        dto.setGender("1");
        dto.setIdentityType("1");

        int result = memberService.insertMember(dto);

        assertEquals(1, result);
    }

    /**
     * 测试新增教师会员
     */
    @Test
    public void testInsertTeacherMember() {
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000002");
        dto.setNickname("测试教师");
        dto.setGender("2");
        dto.setIdentityType("2");
        dto.setRegionId(111L);
        dto.setSchoolId(1L);
        dto.setSchoolGradeId(1L);
        dto.setSchoolClassId(1L);

        int result = memberService.insertMember(dto);

        assertEquals(1, result);
    }

    /**
     * 测试新增教师会员但未填写学校信息（应失败）
     */
    @Test
    public void testInsertTeacherMemberWithoutSchoolInfo() {
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000003");
        dto.setIdentityType("2");

        assertThrows(ServiceException.class, () -> {
            memberService.insertMember(dto);
        });
    }

    /**
     * 测试查询会员列表
     */
    @Test
    public void testSelectMemberList() {
        MemberDTO query = new MemberDTO();
        query.setPageNum(1);
        query.setPageSize(10);

        TableDataInfo result = memberService.selectMemberList(query);

        assertNotNull(result);
        assertNotNull(result.getRows());
    }

    /**
     * 测试根据ID查询会员
     */
    @Test
    public void testGetMemberById() {
        // 先插入一个会员
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000004");
        dto.setIdentityType("1");
        memberService.insertMember(dto);

        // 查询刚插入的会员
        Member member = memberService.getMemberByPhone("13900000004");
        assertNotNull(member);

        MemberVO vo = memberService.getMemberById(member.getMemberId());
        assertNotNull(vo);
        assertEquals("13900000004", vo.getPhoneFull());
    }

    /**
     * 测试修改会员
     */
    @Test
    public void testUpdateMember() {
        // 先插入一个会员
        MemberDTO insertDto = new MemberDTO();
        insertDto.setPhone("13900000005");
        insertDto.setNickname("原昵称");
        insertDto.setIdentityType("1");
        memberService.insertMember(insertDto);

        Member member = memberService.getMemberByPhone("13900000005");
        assertNotNull(member);

        // 修改会员
        MemberDTO updateDto = new MemberDTO();
        updateDto.setMemberId(member.getMemberId());
        updateDto.setPhone("13900000005");
        updateDto.setNickname("新昵称");
        updateDto.setIdentityType("1");

        int result = memberService.updateMember(updateDto);
        assertEquals(1, result);

        // 验证修改结果
        MemberVO vo = memberService.getMemberById(member.getMemberId());
        assertEquals("新昵称", vo.getNickname());
    }

    /**
     * 测试删除会员
     */
    @Test
    public void testDeleteMember() {
        // 先插入一个会员
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000006");
        dto.setIdentityType("1");
        memberService.insertMember(dto);

        Member member = memberService.getMemberByPhone("13900000006");
        assertNotNull(member);

        // 删除会员
        int result = memberService.deleteMember(member.getMemberId());
        assertEquals(1, result);

        // 验证已删除（软删除）
        Member deletedMember = memberService.getMemberByPhone("13900000006");
        assertNull(deletedMember);
    }

    /**
     * 测试重置密码
     */
    @Test
    public void testResetPassword() {
        // 先插入一个会员
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000007");
        dto.setIdentityType("1");
        memberService.insertMember(dto);

        Member member = memberService.getMemberByPhone("13900000007");
        assertNotNull(member);

        // 重置密码
        String newPassword = memberService.resetPassword(member.getMemberId());

        assertNotNull(newPassword);
        assertEquals(8, newPassword.length());
    }

    /**
     * 测试修改状态
     */
    @Test
    public void testChangeStatus() {
        // 先插入一个会员
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000008");
        dto.setIdentityType("1");
        memberService.insertMember(dto);

        Member member = memberService.getMemberByPhone("13900000008");
        assertNotNull(member);

        // 修改状态为停用
        int result = memberService.changeStatus(member.getMemberId(), "1");
        assertEquals(1, result);

        // 验证状态已修改
        MemberVO vo = memberService.getMemberById(member.getMemberId());
        assertEquals("1", vo.getStatus());
    }

    /**
     * 测试手机号唯一性校验
     */
    @Test
    public void testCheckPhoneUnique() {
        // 先插入一个会员
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000009");
        dto.setIdentityType("1");
        memberService.insertMember(dto);

        // 检查手机号唯一性
        boolean unique1 = memberService.checkPhoneUnique("13900000009", null);
        assertFalse(unique1); // 已存在，不唯一

        boolean unique2 = memberService.checkPhoneUnique("13900000099", null);
        assertTrue(unique2); // 不存在，唯一
    }

    /**
     * 测试手机号重复新增（应失败）
     */
    @Test
    public void testInsertMemberWithDuplicatePhone() {
        // 先插入一个会员
        MemberDTO dto1 = new MemberDTO();
        dto1.setPhone("13900000010");
        dto1.setIdentityType("1");
        memberService.insertMember(dto1);

        // 再次插入相同手机号
        MemberDTO dto2 = new MemberDTO();
        dto2.setPhone("13900000010");
        dto2.setIdentityType("1");

        assertThrows(ServiceException.class, () -> {
            memberService.insertMember(dto2);
        });
    }

    /**
     * 测试会员编号生成
     */
    @Test
    public void testMemberCodeGeneration() {
        MemberDTO dto1 = new MemberDTO();
        dto1.setPhone("13900000011");
        dto1.setIdentityType("1");
        memberService.insertMember(dto1);

        MemberDTO dto2 = new MemberDTO();
        dto2.setPhone("13900000012");
        dto2.setIdentityType("1");
        memberService.insertMember(dto2);

        Member member1 = memberService.getMemberByPhone("13900000011");
        Member member2 = memberService.getMemberByPhone("13900000012");

        assertNotNull(member1.getMemberCode());
        assertNotNull(member2.getMemberCode());
        assertNotEquals(member1.getMemberCode(), member2.getMemberCode());
        assertTrue(member1.getMemberCode().startsWith("JS"));
        assertTrue(member2.getMemberCode().startsWith("JS"));
    }

    /**
     * 测试默认昵称生成
     */
    @Test
    public void testDefaultNicknameGeneration() {
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000013");
        dto.setIdentityType("1");
        // 不设置昵称

        memberService.insertMember(dto);

        Member member = memberService.getMemberByPhone("13900000013");
        assertNotNull(member.getNickname());
        assertTrue(member.getNickname().startsWith("用户"));
    }

    /**
     * 测试根据手机号查询会员
     */
    @Test
    public void testGetMemberByPhone() {
        MemberDTO dto = new MemberDTO();
        dto.setPhone("13900000014");
        dto.setNickname("测试查询");
        dto.setIdentityType("1");
        memberService.insertMember(dto);

        Member member = memberService.getMemberByPhone("13900000014");

        assertNotNull(member);
        assertEquals("测试查询", member.getNickname());
    }
}
