package org.dromara.main.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.main.domain.MainStudent;
import org.dromara.main.domain.MainStudentEducation;
import org.dromara.main.domain.MainStudentExperience;
import org.dromara.main.domain.MainStudentProject;
import org.dromara.main.domain.bo.MainStudentBo;
import org.dromara.main.domain.vo.MainStudentVo;

import org.dromara.main.domain.vo.MiniappLoginVo;
import org.dromara.main.mapper.MainStudentEducationMapper;
import org.dromara.main.mapper.MainStudentExperienceMapper;
import org.dromara.main.mapper.MainStudentMapper;
import org.dromara.main.mapper.MainStudentProjectMapper;
import org.dromara.main.service.IMainStudentService;
import org.dromara.main.utils.WechatMiniAppUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;


@RequiredArgsConstructor
@Service
public class MainStudentServiceImpl implements IMainStudentService {

    private final MainStudentMapper baseMapper;
    private final MainStudentEducationMapper educationMapper;
    private final MainStudentProjectMapper projectMapper;
    private final MainStudentExperienceMapper experienceMapper;

    @Override
    public MainStudentVo queryById(Long id){
        MainStudentVo vo = baseMapper.selectVoById(id);
        if(vo != null){
            vo.setEducationList(educationMapper.selectVoList(new LambdaQueryWrapper<MainStudentEducation>()
                    .eq(MainStudentEducation::getStudentId, id)));
            vo.setExperienceList(experienceMapper.selectVoList(new LambdaQueryWrapper<MainStudentExperience>()
                    .eq(MainStudentExperience::getStudentId, id)));
            vo.setProjectList(projectMapper.selectVoList(new LambdaQueryWrapper<MainStudentProject>()
                    .eq(MainStudentProject::getStudentId, id)));
        }
        return vo;
    }

    @Override
    public TableDataInfo<MainStudentVo> queryPageList(MainStudentBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<MainStudent> lqw = buildQueryWrapper(bo);
        Page<MainStudentVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public List<MainStudentVo> queryList(MainStudentBo bo) {
        LambdaQueryWrapper<MainStudent> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<MainStudent> buildQueryWrapper(MainStudentBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<MainStudent> lqw = Wrappers.lambdaQuery();
        lqw.eq(ObjectUtil.isNotNull(bo.getStudentNo()), MainStudent::getStudentNo, bo.getStudentNo());
        lqw.like(ObjectUtil.isNotNull(bo.getName()), MainStudent::getName, bo.getName());
        lqw.eq(ObjectUtil.isNotNull(bo.getMobile()), MainStudent::getMobile, bo.getMobile());
        lqw.eq(ObjectUtil.isNotNull(bo.getEmail()), MainStudent::getEmail, bo.getEmail());
        lqw.eq(ObjectUtil.isNotNull(bo.getIdCardNumber()), MainStudent::getIdCardNumber, bo.getIdCardNumber());
        lqw.eq(ObjectUtil.isNotNull(bo.getGender()), MainStudent::getGender, bo.getGender());
        lqw.eq(ObjectUtil.isNotNull(bo.getUserType()), MainStudent::getUserType, bo.getUserType());
        lqw.eq(ObjectUtil.isNotNull(bo.getJobType()), MainStudent::getJobType, bo.getJobType());
        lqw.like(ObjectUtil.isNotNull(bo.getSchoolName()), MainStudent::getSchoolName, bo.getSchoolName());
        lqw.eq(ObjectUtil.isNotNull(bo.getEducation()), MainStudent::getEducation, bo.getEducation());
        lqw.eq(ObjectUtil.isNotNull(bo.getStatus()), MainStudent::getStatus, bo.getStatus());
        return lqw;
    }

    @Override
    public Boolean insertByBo(MainStudentBo bo) {
        MainStudent add = BeanUtil.toBean(bo, MainStudent.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(MainStudentBo bo) {
        MainStudent update = BeanUtil.toBean(bo, MainStudent.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    private void validEntityBeforeSave(MainStudent entity){
        // TODO 做一些数据校验,例如唯一性校验
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            // TODO 做一些业务上的校验,判断是否可删除
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Boolean updateStatus(Long id,String status){
        MainStudent student=new MainStudent();
        student.setId(id);
        student.setStatus( status);
        return baseMapper.updateById(student) > 0;
    }

    @Override
    public Boolean updateUserType(Long id, String userType) {
        MainStudent student = new MainStudent();
        student.setId(id);
        student.setUserType(userType);
        return baseMapper.updateById(student) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MiniappLoginVo miniAppLogin(String code, String phoneCode) {
        // 1. 调用微信接口, 用 code 换取 openid 和 session_key
        JSONObject sessionData = WechatMiniAppUtil.code2Session(code);
        if (sessionData == null) {
            throw new ServiceException("微信登录失败,请重试");
        }
        String openid = sessionData.getStr("openid");
        String sessionKey = sessionData.getStr("session_key");
        String unionId = sessionData.getStr("unionid");
        if (StringUtils.isBlank(openid)) {
            throw new ServiceException("获取微信openid失败");
        }
        // 2. 获取手机号
        JSONObject phoneInfo = WechatMiniAppUtil.getPhoneNumberByCode(phoneCode);
        if (phoneInfo == null) {
            throw new ServiceException("获取手机号失败，请重试");
        }
        String phoneNumber = phoneInfo.getStr("purePhoneNumber");
        if (StringUtils.isBlank(phoneNumber)) {
            throw new ServiceException("获取手机号失败");
        }
        // 3. 查询或创建学员账号
        boolean isNewUser = false;

        // 优先根据 openid 查询
        MainStudent student = baseMapper.selectOne(
            Wrappers.lambdaQuery(MainStudent.class).eq(MainStudent::getOpenid, openid)
        );
        if (student != null) {
            // 已有记录，更新最新数据
            student.setSessionKey(sessionKey);
            student.setMobile(phoneNumber);
            if (StringUtils.isNotBlank(unionId)) {
                student.setUnionId(unionId);
            }
            baseMapper.updateById(student);
        } else {
            // openid 未查询到，根据手机号查询
            student = baseMapper.selectOne(
                Wrappers.lambdaQuery(MainStudent.class).eq(MainStudent::getMobile, phoneNumber)
            );

            if (student != null) {
                // 绑定到已有手机号账号
                student.setOpenid(openid);
                student.setSessionKey(sessionKey);
                if (StringUtils.isNotBlank(unionId)) {
                    student.setUnionId(unionId);
                }
                baseMapper.updateById(student);
            } else {
                // 新用户，执行创建
                isNewUser = true;
                student = new MainStudent();
                student.setName("用户_" + RandomUtil.randomString(6));
                student.setGender("");
                student.setOpenid(openid);
                student.setSessionKey(sessionKey);
                student.setUnionId(unionId);
                student.setMobile(phoneNumber);
                student.setUserType("2"); // 2: 标识为普通用户/新学员
                student.setStatus("0");   // 0: 正常状态
                baseMapper.insert(student);
            }
        }
        String clientId = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY);
        if (clientId == null || clientId.isEmpty()) {
            clientId = "e5cd7e4891bf95d1d19206ce24a7b32e"; // 给个兜底默认值
        }
        SaLoginParameter loginModel = new SaLoginParameter()
            .setDevice("app") // 后端可用于区分设备，控制互踢逻辑
            .setExtra(LoginHelper.CLIENT_KEY, clientId)
            .setExtra(LoginHelper.USER_KEY, student.getId())
            .setExtra(LoginHelper.USER_NAME_KEY, student.getName());
        StpUtil.login(student.getId(), loginModel);
        String token = StpUtil.getTokenValue();
        // 5. 组合组装返回结果
        MiniappLoginVo result = new MiniappLoginVo();
        result.setToken(token);
        result.setStudentId(student.getId());
        result.setMobile(student.getMobile());
        result.setName(student.getName());
        result.setIsNewUser(isNewUser);
        // 获取完整的学员信息以获取头像URL
        MainStudentVo studentVo = baseMapper.selectVoById(student.getId());
        if (studentVo != null) {
            result.setAvatarUrl(studentVo.getAvatarUrl());
        }
        return result;
    }
}
