package com.ruoyi.web.modules.account.service.impl;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.modules.account.constant.MemberConstants;
import com.ruoyi.web.modules.account.domain.BizMember;
import com.ruoyi.web.modules.account.dto.MemberCreateDTO;
import com.ruoyi.web.modules.account.dto.MemberLoginDTO;
import com.ruoyi.web.modules.account.dto.MemberRegisterDTO;
import com.ruoyi.web.modules.account.mapper.BizMemberMapper;
import com.ruoyi.web.modules.account.service.IMemberAppService;
import com.ruoyi.web.modules.account.service.IMemberSmsService;
import com.ruoyi.web.modules.account.service.IMemberTokenService;
import com.ruoyi.web.modules.account.support.MemberRegistrationSupport;
import com.ruoyi.web.modules.content.facade.IMallServiceAgreementFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * C 端会员 Service 实现
 */
@Service
public class MemberAppServiceImpl implements IMemberAppService
{
    @Autowired
    private BizMemberMapper memberMapper;

    @Autowired
    private IMemberSmsService smsService;

    @Autowired
    private IMemberTokenService tokenService;

    @Autowired
    private IMallServiceAgreementFacade mallServiceAgreementFacade;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private MemberRegistrationSupport memberRegistrationSupport;

    @Override
    public void sendSms(String mobile)
    {
        smsService.sendCode(mobile);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long register(MemberRegisterDTO dto)
    {
        validateRegister(dto);
        mallServiceAgreementFacade.assertAcceptedForRegister(Boolean.TRUE.equals(dto.getAgreementAccepted()));
        if (memberMapper.countByMobile(dto.getMobile(), null) > 0)
        {
            throw new ServiceException("手机号已注册");
        }
        if (!smsService.verifyCode(dto.getMobile(), dto.getSmsCode()))
        {
            throw new ServiceException("验证码错误或已过期");
        }

        MemberCreateDTO create = new MemberCreateDTO();
        create.setMobile(dto.getMobile());
        create.setPassword(dto.getPassword());
        create.setMemberCode(dto.getMemberCode());
        create.setNickName(dto.getNickName());
        return memberRegistrationSupport.createMember(create, "member");
    }

    @Override
    public Map<String, Object> login(MemberLoginDTO dto)
    {
        if (dto == null || StringUtils.isEmpty(dto.getMobile()) || StringUtils.isEmpty(dto.getPassword()))
        {
            throw new ServiceException("请输入手机号和密码");
        }
        mallServiceAgreementFacade.assertAcceptedForLogin(Boolean.TRUE.equals(dto.getAgreementAccepted()));
        BizMember member = memberMapper.selectByMobile(dto.getMobile());
        if (member == null)
        {
            throw new ServiceException("手机号或密码错误");
        }
        if (!MemberConstants.STATUS_ENABLED.equals(member.getStatus()))
        {
            throw new ServiceException("账号已禁用，请联系客服");
        }
        if (!SecurityUtils.matchesPassword(dto.getPassword(), member.getPassword()))
        {
            throw new ServiceException("手机号或密码错误");
        }
        String token = tokenService.createToken(member.getMemberId());
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("memberId", member.getMemberId());
        return result;
    }

    @Override
    public BizMember getProfile(Long memberId)
    {
        BizMember member = memberMapper.selectById(memberId);
        if (member == null)
        {
            throw new ServiceException("会员不存在");
        }
        member.setPassword(null);
        return member;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProfile(Long memberId, BizMember profile)
    {
        BizMember existing = memberMapper.selectById(memberId);
        if (existing == null)
        {
            throw new ServiceException("会员不存在");
        }
        BizMember accountUpdate = new BizMember();
        accountUpdate.setMemberId(memberId);
        accountUpdate.setUpdateBy(String.valueOf(memberId));
        if (StringUtils.isNotEmpty(profile.getMemberCode()))
        {
            if (profile.getMemberCode().length() > 64)
            {
                throw new ServiceException("会员名称过长");
            }
            SysUser check = new SysUser();
            check.setUserId(memberId);
            check.setUserName(profile.getMemberCode());
            if (!sysUserService.checkUserNameUnique(check))
            {
                throw new ServiceException("会员名称已存在");
            }
            accountUpdate.setMemberCode(profile.getMemberCode());
        }
        accountUpdate.setNickName(profile.getNickName());
        accountUpdate.setAvatar(profile.getAvatar());
        if (StringUtils.isNotEmpty(profile.getPassword()))
        {
            accountUpdate.setPassword(SecurityUtils.encryptPassword(profile.getPassword()));
        }
        memberMapper.updateAccount(accountUpdate);

        BizMember bizUpdate = new BizMember();
        bizUpdate.setMemberId(memberId);
        bizUpdate.setMemberLevel(profile.getMemberLevel());
        bizUpdate.setRemark(profile.getRemark());
        bizUpdate.setUpdateBy(String.valueOf(memberId));
        if (profile.getMemberLevel() != null || profile.getRemark() != null)
        {
            memberMapper.update(bizUpdate);
        }
    }

    private void validateRegister(MemberRegisterDTO dto)
    {
        if (dto == null || StringUtils.isEmpty(dto.getMobile()))
        {
            throw new ServiceException("请输入手机号");
        }
        if (StringUtils.isEmpty(dto.getPassword()))
        {
            throw new ServiceException("请输入密码");
        }
        if (StringUtils.isEmpty(dto.getSmsCode()))
        {
            throw new ServiceException("请输入验证码");
        }
    }
}
