package com.pangu.member.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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 com.pangu.member.enums.IdentityTypeEnum;
import com.pangu.member.enums.RegisterSourceEnum;
import com.pangu.member.mapper.MemberMapper;
import com.pangu.member.service.IMemberService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 会员服务实现
 * @author pangu
 */
@Slf4j
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements IMemberService {

    @Autowired
    private MemberMapper memberMapper;
    
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    
    @Lazy
    @Autowired
    private com.pangu.student.service.IStudentService studentService;

    /** 默认密码 */
    private static final String DEFAULT_PASSWORD = "123456";

    /** 重置密码长度 */
    private static final int RESET_PASSWORD_LENGTH = 8;

    @Override
    public TableDataInfo selectMemberList(MemberDTO memberDTO) {
        // 创建分页对象
        Page<MemberVO> page = new Page<>(
            memberDTO.getPageNum() != null ? memberDTO.getPageNum() : 1,
            memberDTO.getPageSize() != null ? memberDTO.getPageSize() : 10
        );

        // 查询数据
        List<MemberVO> list = memberMapper.selectMemberVOList(page, memberDTO);

        // 填充名称字段
        list.forEach(this::fillMemberVONames);

        return new TableDataInfo(list, page.getTotal());
    }

    @Override
    public MemberVO getMemberById(Long memberId) {
        MemberVO memberVO = memberMapper.selectMemberVOById(memberId);
        if (memberVO == null) {
            throw new ServiceException("会员不存在");
        }

        // 填充名称
        fillMemberVONames(memberVO);

        // 查询绑定的学生
        List<com.pangu.student.domain.vo.StudentVO> studentVOList = studentService.selectStudentVOsByMemberId(memberId);
        List<MemberVO.StudentVO> students = studentVOList.stream().map(s -> {
            MemberVO.StudentVO vo = new MemberVO.StudentVO();
            vo.setStudentId(s.getStudentId());
            vo.setStudentName(s.getStudentName());
            vo.setStudentNo(s.getStudentNo());
            vo.setSchoolName(s.getSchoolName());
            vo.setGradeName(s.getGradeName());
            vo.setClassName(s.getClassName());
            return vo;
        }).collect(java.util.stream.Collectors.toList());
        memberVO.setStudents(students);

        return memberVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertMember(MemberDTO memberDTO) {
        // 校验手机号唯一性
        if (!checkPhoneUnique(memberDTO.getPhone(), null)) {
            throw new ServiceException("手机号已存在");
        }

        // 校验教师信息完整性
        if (IdentityTypeEnum.isTeacher(memberDTO.getIdentityType())) {
            validateTeacherInfo(memberDTO);
        }

        // 构建会员对象
        Member member = buildMember(memberDTO);
        member.setMemberCode(generateMemberCode());
        member.setPassword(passwordEncoder.encode(DEFAULT_PASSWORD));
        member.setRegisterSource(RegisterSourceEnum.BACKEND.getCode());
        member.setRegisterTime(LocalDateTime.now());
        member.setLoginCount(0);
        member.setStatus("0");

        // 自动生成昵称
        if (StrUtil.isBlank(member.getNickname())) {
            member.setNickname(generateNickname(member.getPhone()));
        }

        int result = memberMapper.insert(member);

        log.info("新增会员成功, memberId={}, phone={}", member.getMemberId(), member.getPhone());
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateMember(MemberDTO memberDTO) {
        Member existMember = memberMapper.selectById(memberDTO.getMemberId());
        if (existMember == null) {
            throw new ServiceException("会员不存在");
        }

        // 校验手机号唯一性
        if (!checkPhoneUnique(memberDTO.getPhone(), memberDTO.getMemberId())) {
            throw new ServiceException("手机号已存在");
        }

        // 校验教师信息完整性
        if (IdentityTypeEnum.isTeacher(memberDTO.getIdentityType())) {
            validateTeacherInfo(memberDTO);
        }

        // 更新会员信息
        Member member = buildMember(memberDTO);
        member.setMemberId(memberDTO.getMemberId());

        // 如果从教师改为家长，清空学校信息
        if (IdentityTypeEnum.isParent(memberDTO.getIdentityType())) {
            member.setRegionId(null);
            member.setSchoolId(null);
            member.setSchoolGradeId(null);
            member.setSchoolClassId(null);
        }

        int result = memberMapper.updateById(member);
        log.info("更新会员成功, memberId={}", member.getMemberId());
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteMember(Long memberId) {
        // 检查是否可删除
        if (!checkCanDelete(memberId)) {
            throw new ServiceException("该会员已绑定学生，请先解绑学生后再删除");
        }

        int result = memberMapper.deleteById(memberId);
        log.info("删除会员成功, memberId={}", memberId);
        return result;
    }

    @Override
    public String resetPassword(Long memberId) {
        Member member = memberMapper.selectById(memberId);
        if (member == null) {
            throw new ServiceException("会员不存在");
        }

        // 生成随机密码
        String newPassword = RandomUtil.randomString(RESET_PASSWORD_LENGTH);

        // 更新密码
        Member updateMember = new Member();
        updateMember.setMemberId(memberId);
        updateMember.setPassword(passwordEncoder.encode(newPassword));
        memberMapper.updateById(updateMember);

        log.info("重置会员密码成功, memberId={}", memberId);
        return newPassword;
    }

    @Override
    public int changeStatus(Long memberId, String status) {
        Member member = new Member();
        member.setMemberId(memberId);
        member.setStatus(status);

        int result = memberMapper.updateById(member);
        log.info("修改会员状态成功, memberId={}, status={}", memberId, status);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int bindStudent(Long memberId, Long studentId) {
        Member member = memberMapper.selectById(memberId);
        if (member == null) {
            throw new ServiceException("会员不存在");
        }

        // 教师只能绑定本校学生
        if (IdentityTypeEnum.isTeacher(member.getIdentityType())) {
            if (!studentService.isStudentInSchool(studentId, member.getSchoolId())) {
                throw new ServiceException("教师只能绑定本校学生");
            }
        }

        // 更新学生的memberId
        int result = studentService.updateStudentMember(studentId, memberId);
        log.info("绑定学生成功, memberId={}, studentId={}", memberId, studentId);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int unbindStudent(Long memberId, Long studentId) {
        // 解绑学生
        int result = studentService.unbindStudent(studentId);
        log.info("解绑学生成功, memberId={}, studentId={}", memberId, studentId);
        return result;
    }

    @Override
    public boolean checkPhoneUnique(String phone, Long memberId) {
        return memberMapper.countByPhone(phone, memberId) == 0;
    }

    @Override
    public boolean checkCanDelete(Long memberId) {
        // 检查是否有绑定的学生
        return studentService.countByMemberId(memberId) == 0;
    }

    @Override
    public Member getMemberByPhone(String phone) {
        return memberMapper.selectByPhone(phone);
    }

    @Override
    public Member getMemberByOpenId(String openId) {
        return memberMapper.selectByOpenId(openId);
    }

    /**
     * 构建会员对象
     */
    private Member buildMember(MemberDTO dto) {
        Member member = new Member();
        member.setPhone(dto.getPhone());
        member.setNickname(dto.getNickname());
        member.setGender(dto.getGender());
        member.setBirthday(dto.getBirthday());
        member.setIdentityType(dto.getIdentityType());
        member.setRegionId(dto.getRegionId());
        member.setSchoolId(dto.getSchoolId());
        member.setSchoolGradeId(dto.getSchoolGradeId());
        member.setSchoolClassId(dto.getSchoolClassId());
        member.setStatus(dto.getStatus());
        return member;
    }

    /**
     * 校验教师信息完整性
     */
    private void validateTeacherInfo(MemberDTO memberDTO) {
        if (memberDTO.getRegionId() == null) {
            throw new ServiceException("请选择所属区域");
        }
        if (memberDTO.getSchoolId() == null) {
            throw new ServiceException("请选择所属学校");
        }
        if (memberDTO.getSchoolGradeId() == null) {
            throw new ServiceException("请选择所属年级");
        }
        if (memberDTO.getSchoolClassId() == null) {
            throw new ServiceException("请选择所属班级");
        }
    }

    /**
     * 生成会员编号
     * 格式：JS + 时间戳
     */
    private String generateMemberCode() {
        return "JS" + System.currentTimeMillis();
    }

    /**
     * 生成默认昵称
     */
    private String generateNickname(String phone) {
        if (StrUtil.isBlank(phone) || phone.length() < 4) {
            return "用户" + RandomUtil.randomNumbers(4);
        }
        return "用户" + phone.substring(phone.length() - 4);
    }

    /**
     * 填充VO的名称字段
     */
    private void fillMemberVONames(MemberVO vo) {
        // 性别名称
        vo.setGenderName(getGenderName(vo.getGender()));
        // 身份类型名称
        vo.setIdentityTypeName(IdentityTypeEnum.getNameByCode(vo.getIdentityType()));
        // 注册来源名称
        vo.setRegisterSourceName(RegisterSourceEnum.getNameByCode(vo.getRegisterSource()));
    }

    /**
     * 获取性别名称
     */
    private String getGenderName(String gender) {
        return switch (gender) {
            case "1" -> "男";
            case "2" -> "女";
            default -> "未知";
        };
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long getOrCreateMemberByPhone(String phone) {
        // 先查询是否存在
        Member existMember = getMemberByPhone(phone);
        if (existMember != null) {
            return existMember.getMemberId();
        }
        
        // 不存在则创建
        Member newMember = new Member();
        newMember.setMemberCode(generateMemberCode());
        newMember.setPhone(phone);
        newMember.setNickname(generateNickname(phone));
        newMember.setPassword(passwordEncoder.encode(DEFAULT_PASSWORD));
        newMember.setIdentityType(IdentityTypeEnum.PARENT.getCode());
        newMember.setRegisterSource(RegisterSourceEnum.BACKEND.getCode());
        newMember.setStatus("0");
        newMember.setRegisterTime(LocalDateTime.now());
        
        memberMapper.insert(newMember);
        log.info("批量导入自动创建会员, memberId={}, phone={}", newMember.getMemberId(), phone);
        
        return newMember.getMemberId();
    }
}
