package shop.alien.lawyer.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import shop.alien.entity.result.R;

import shop.alien.entity.store.LawyerServiceArea;
import shop.alien.entity.store.LawyerUser;

import shop.alien.entity.store.dto.LawyerUserDto;
import shop.alien.entity.store.vo.LawyerUserVo;
import shop.alien.lawyer.config.BaseRedisService;
import shop.alien.lawyer.service.LawyerUserLogInService;
import shop.alien.lawyer.service.LawyerUserService;
import shop.alien.mapper.LawyerServiceAreaMapper;
import shop.alien.mapper.LawyerUserMapper;
import shop.alien.util.common.JwtUtil;

import java.util.*;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

/**
 * 二期-门店用户 服务实现类
 *
 * @author ssk
 * @since 2024-12-11
 */
@Transactional
@Service
@RequiredArgsConstructor
public class LawyerUserLogInServiceImpl extends ServiceImpl<LawyerUserMapper, LawyerUser> implements LawyerUserLogInService {

    private static final DateTimeFormatter LOGOUT_END_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy/MM/dd");

    @Value("${jwt.expiration-time}")
    private String effectiveTime;

    /**
     * 设定初始化默认密码
     */

    private final BaseRedisService baseRedisService;
    private final LawyerUserMapper lawyerUserMapper;
    private final LawyerServiceAreaMapper lawyerServiceAreaMapper;
    private final LawyerUserService lawyerUserService;

    /**
     * token
     *
     * @param lawyerUser
     * @return
     */
    @Override
    public R<LawyerUserVo> createToKen(LawyerUser lawyerUser) {
        int effectiveTimeInt = Integer.parseInt(effectiveTime.substring(0, effectiveTime.length() - 1));
        String effectiveTimeUnit = effectiveTime.substring(effectiveTime.length() - 1);
        long effectiveTimeIntLong = 0L;
        switch (effectiveTimeUnit) {
            case "s": {
                effectiveTimeIntLong = effectiveTimeInt * 1000L;
                break;
            }
            case "m": {
                effectiveTimeIntLong = effectiveTimeInt * 60L * 1000L;
                break;
            }
            case "h": {
                effectiveTimeIntLong = effectiveTimeInt * 60L * 60L * 1000L;
                break;
            }
            case "d": {
                effectiveTimeIntLong = effectiveTimeInt * 24L * 60L * 60L * 1000L;
                break;
            }
        }

        LawyerUserVo lawyerUserVo = new LawyerUserVo();
        BeanUtils.copyProperties(lawyerUser, lawyerUserVo);
        lawyerUserVo.setLogoutEndTime(resolveLogoutEndTime(lawyerUser.getLogoutTime(), lawyerUser.getLogoutFlag()));
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("phone", lawyerUser.getPhone());
        tokenMap.put("userName", lawyerUser.getName());
        tokenMap.put("userId", lawyerUser.getId().toString());
        tokenMap.put("userType", "lawyer");
        tokenMap.put("passType", lawyerUser.getPassType().toString());
        lawyerUserVo.setToken(JwtUtil.createJWT("lawyer_" + lawyerUser.getPhone(), lawyerUser.getName(), JSONObject.toJSONString(tokenMap), effectiveTimeIntLong));
        baseRedisService.setString("lawyer_" + lawyerUser.getPhone(), lawyerUserVo.getToken());
        log.debug("token:-------------------------------------------");
        log.debug(lawyerUserVo.getToken());
        return R.data(lawyerUserVo);
    }

    /**
     * 申请注销结束时间：logoutTime 起算第 7 天（T+0～T+7），与冷静期一致。
     */
    private static String resolveLogoutEndTime(Date logoutTime, Integer logoutFlag) {
        if (logoutTime == null || logoutFlag == null || LawyerUser.LOGOUT_FLAG_COOLING != logoutFlag) {
            return null;
        }
        return logoutTime.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate()
                .plusDays(7)
                .format(LOGOUT_END_TIME_FORMAT);
    }

    @Override
    public R<LawyerUserVo> register(LawyerUserDto lawyerUserDto) {
        LawyerUser lawyerUser = lawyerUserMapper.selectOne(new LambdaQueryWrapper<LawyerUser>()
                .eq(LawyerUser::getPhone, lawyerUserDto.getPhone()).eq(LawyerUser::getDeleteFlag, 0).last("limit 1"));
        if (ObjectUtils.isNotEmpty(lawyerUser)) {
            if (lawyerUser.getStatus() == 0) {
                return R.fail("账号被禁用");
            }
            if (lawyerUser.getLogoutFlag() != null && LawyerUser.LOGOUT_FLAG_DONE == lawyerUser.getLogoutFlag()
                    && (lawyerUser.getDeleteFlag() == null || lawyerUser.getDeleteFlag() == 0)) {
                return R.fail("账号已注销");
            }
            return createToKen(lawyerUser);
        }else {
            LawyerUser user = new LawyerUser();
            BeanUtils.copyProperties(lawyerUserDto, user);
            String certNo = user.getLawyerCertificateNo();
            if (certNo != null && !certNo.trim().isEmpty()) {
                certNo = certNo.trim();
                user.setLawyerCertificateNo(certNo);
                LawyerUser certDup = lawyerUserMapper.selectOne(new LambdaQueryWrapper<LawyerUser>()
                        .eq(LawyerUser::getLawyerCertificateNo, certNo)
                        .eq(LawyerUser::getDeleteFlag, 0)
                        .last("limit 1"));
                if (certDup != null) {
                    return R.fail("该律师执业证号已被使用，无法重复注册");
                }
            }
            user.setLogoutFlag(LawyerUser.LOGOUT_FLAG_NORMAL);
            user.setStatus(1);
            user.setDeleteFlag(0);
            user.setIsOnline(1);
            user.setIsRecommended(0);
            user.setOrderReceivingStatus(1);
            user.setPassType(2);
            user.setNickName(user.getName() != null && !user.getName().isEmpty() ?
                    user.getName().charAt(0) + "律师" : "律师");
            lawyerUserMapper.insert(user);
            List<Integer> problemScenarioIds = lawyerUserDto.getProblemScenarioIds();
            for (int i = 0; i < problemScenarioIds.size(); i++) {
                LawyerServiceArea lawyerServiceArea = new LawyerServiceArea();
                lawyerServiceArea.setLawyerUserId(user.getId());
                lawyerServiceArea.setProblemScenarioId(problemScenarioIds.get( i));
                lawyerServiceArea.setSortOrder(i);
                lawyerServiceArea.setCreatedTime(new Date());
                lawyerServiceAreaMapper.insert(lawyerServiceArea);
            }
            /*LambdaQueryWrapper<LawyerUser> lawFirmLambdaQueryWrapper = new LambdaQueryWrapper<>();
            lawFirmLambdaQueryWrapper.eq(LawyerUser::getFirmId, lawyerUserDto.getFirmId());
            List<LawyerUser> lawyerUsers = lawyerUserMapper.selectList(lawFirmLambdaQueryWrapper);
            if (ObjectUtils.isNotEmpty(lawyerUsers)) {
                String lawFirmIds = lawyerUsers.stream().map(u -> String.valueOf(u.getFirmId())).filter(Objects::nonNull).distinct().collect(Collectors.joining(","));
                LawFirm lawFirm = new LawFirm();
                lawFirm.setId(lawyerUserDto.getFirmId());
                lawFirm.setPaymentAccount(lawFirmIds);
                lawFirmMapper.updateById(lawFirm);
            }*/
            return createToKen(user);
        }
    }

    @Override
    public R<LawyerUserVo> completeProfile(LawyerUserDto lawyerUserDto) {
        if (lawyerUserDto == null || StringUtils.isEmpty(lawyerUserDto.getPhone())) {
            return R.fail("手机号不能为空");
        }
        LawyerUser lawyerUser = lawyerUserMapper.selectOne(new LambdaQueryWrapper<LawyerUser>()
                .eq(LawyerUser::getPhone, lawyerUserDto.getPhone())
                .eq(LawyerUser::getDeleteFlag, 0)
                .last("limit 1"));
        if (ObjectUtils.isEmpty(lawyerUser)) {
            return R.fail("当前账号不存在，请先登录");
        }
        if (lawyerUser.getStatus() != null && lawyerUser.getStatus() == 0) {
            return R.fail("账号被禁用");
        }
        if (lawyerUser.getLogoutFlag() != null && LawyerUser.LOGOUT_FLAG_DONE == lawyerUser.getLogoutFlag()) {
            return R.fail("账号已注销");
        }

        String certNo = lawyerUserDto.getLawyerCertificateNo();
        if (certNo != null && !certNo.trim().isEmpty()) {
            certNo = certNo.trim();
            LawyerUser certDup = lawyerUserMapper.selectOne(new LambdaQueryWrapper<LawyerUser>()
                    .eq(LawyerUser::getLawyerCertificateNo, certNo)
                    .eq(LawyerUser::getDeleteFlag, 0)
                    .ne(LawyerUser::getId, lawyerUser.getId())
                    .last("limit 1"));
            if (certDup != null) {
                return R.fail("该律师执业证号已被使用，无法重复注册");
            }
        }

        LawyerUser update = new LawyerUser();
        BeanUtils.copyProperties(lawyerUserDto, update);
        update.setId(lawyerUser.getId());
        update.setPhone(lawyerUser.getPhone());
        update.setLogoutFlag(lawyerUser.getLogoutFlag());
        update.setStatus(lawyerUser.getStatus());
        update.setDeleteFlag(lawyerUser.getDeleteFlag());
        if (certNo != null && !certNo.isEmpty()) {
            update.setLawyerCertificateNo(certNo);
        }
        if (update.getName() != null && !update.getName().isEmpty()) {
            update.setNickName(update.getName().charAt(0) + "律师");
        }
        if (update.getPassType() == null) {
            update.setPassType(lawyerUser.getPassType() != null ? lawyerUser.getPassType() : 2);
        }
        if (update.getIsOnline() == null) {
            update.setIsOnline(lawyerUser.getIsOnline() != null ? lawyerUser.getIsOnline() : 1);
        }
        if (update.getIsRecommended() == null) {
            update.setIsRecommended(0);
        }
        if (update.getOrderReceivingStatus() == null) {
            update.setOrderReceivingStatus(1);
        }
        lawyerUserMapper.updateById(update);

        List<Integer> problemScenarioIds = lawyerUserDto.getProblemScenarioIds();
        if (!CollectionUtils.isEmpty(problemScenarioIds)) {
            UpdateWrapper<LawyerServiceArea> deleteWrapper = new UpdateWrapper<>();
            deleteWrapper.eq("lawyer_user_id", lawyerUser.getId())
                    .set("delete_flag", 1)
                    .set("updated_time", new Date());
            lawyerServiceAreaMapper.update(null, deleteWrapper);
            for (int i = 0; i < problemScenarioIds.size(); i++) {
                LawyerServiceArea lawyerServiceArea = new LawyerServiceArea();
                lawyerServiceArea.setLawyerUserId(lawyerUser.getId());
                lawyerServiceArea.setProblemScenarioId(problemScenarioIds.get(i));
                lawyerServiceArea.setSortOrder(i);
                lawyerServiceArea.setCreatedTime(new Date());
                lawyerServiceAreaMapper.insert(lawyerServiceArea);
            }
        }

        return lawyerUserService.getLawyerInfo(lawyerUser.getId());
    }

    @Override
    public R checkMsgCode(LawyerUserDto lawyerUserDto) {
        String string = baseRedisService.getString("verification_lawyer_" + lawyerUserDto.getPhone());
        if (StringUtils.isNotEmpty(string)) {
            if (lawyerUserDto.getMsgCode().equals(string)) {
                LawyerUser lawyerUser = lawyerUserMapper.selectOne(new LambdaQueryWrapper<LawyerUser>()
                        .eq(LawyerUser::getPhone, lawyerUserDto.getPhone()));
                LawyerUserVo vo = new LawyerUserVo();
                if (ObjectUtils.isNotEmpty(lawyerUser)) {
                    if (lawyerUser.getStatus() != null && lawyerUser.getStatus() == 0) {
                        return R.fail("账号被禁用");
                    }
                    if (lawyerUser.getLogoutFlag() != null && LawyerUser.LOGOUT_FLAG_DONE == lawyerUser.getLogoutFlag()
                            && (lawyerUser.getDeleteFlag() == null || lawyerUser.getDeleteFlag() == 0)
                            && LawyerUser.isWithinReRegisterBlockPeriod(lawyerUser.getLogoutTime())) {
                        return R.fail("账号已注销");
                    }
                    BeanUtils.copyProperties(lawyerUser, vo);
                    return createToKen(lawyerUser);
                }
                return R.data(ObjectUtils.isNotEmpty(lawyerUser) ? vo : "null");
            }else {
                return R.fail("验证码错误，请重新输入");
            }
        }else {
            return R.fail("验证码已过期");
        }
    }

    @Override
    public R<LawyerUserVo> login(LawyerUserDto lawyerUserDto) {
        if (lawyerUserDto == null || StringUtils.isEmpty(lawyerUserDto.getPhone())) {
            return R.fail("手机号不能为空");
        }
        boolean passwordLogin = Boolean.TRUE.equals(lawyerUserDto.getIsPassword());
        LawyerUser lawyerUser = findActiveLawyerByPhone(lawyerUserDto.getPhone());
        if (lawyerUser == null) {
            if (passwordLogin) {
                return R.fail("当前账号不存在，请先去注册账号");
            }
            lawyerUser = createLawyerOnLogin(lawyerUserDto.getPhone());
        }
        R<LawyerUser> loginCheck = lawyerUserService.checkLogin(lawyerUserDto.getPhone());
        if ("账号已注销".equals(loginCheck.getMsg())) {
            return R.fail("账号已注销");
        }
        if ("账号已被禁用".equals(loginCheck.getMsg())) {
            return R.fail("账号被禁用");
        }
        LawyerUser onlineUpdate = new LawyerUser();
        onlineUpdate.setId(lawyerUser.getId());
        onlineUpdate.setIsOnline(1);
        lawyerUserMapper.updateById(onlineUpdate);
        if (passwordLogin) {
            return checkPassword(lawyerUser, lawyerUserDto.getPassword());
        }
        return createToKen(lawyerUser);
    }

    private LawyerUser findActiveLawyerByPhone(String phone) {
        return lawyerUserMapper.selectOne(new LambdaQueryWrapper<LawyerUser>()
                .eq(LawyerUser::getPhone, phone)
                .eq(LawyerUser::getDeleteFlag, 0)
                .orderByDesc(LawyerUser::getCreatedTime)
                .last("LIMIT 1"));
    }

    private LawyerUser createLawyerOnLogin(String phone) {
        LawyerUser user = new LawyerUser();
        user.setIsOnline(1);
        user.setPhone(phone);
        user.setName(phone);
        user.setPassType(2);
        lawyerUserMapper.insert(user);
        return user;
    }

    private R<LawyerUserVo> checkPassword(LawyerUser lawyerUser, String password) {
        if (StringUtils.isEmpty(password)) {
            return R.fail("密码不能为空");
        }
        if (StringUtils.isEmpty(lawyerUser.getPassword())) {
            return R.fail("尚未设置登录密码，请使用验证码登录或设置密码");
        }
        return Objects.equals(password, lawyerUser.getPassword())
                ? createToKen(lawyerUser)
                : R.fail("密码错误");
    }

    @Override
    public R logout(LawyerUserDto lawyerUserDto) {
        LawyerUser lawyerUser = new LawyerUser();
        lawyerUser.setId(lawyerUserDto.getId());
        lawyerUser.setLastOnlineTime(new Date());
        lawyerUser.setIsOnline(0);
        lawyerUserMapper.updateById(lawyerUser);
        baseRedisService.delete("lawyer_" + lawyerUserDto.getPhone());
        return R.success("退出成功");
    }

    @Override
    public R updatePassWord(LawyerUserDto lawyerUserDto) {
        String string = baseRedisService.getString("verification_lawyer_" + lawyerUserDto.getPhone());
        if (StringUtils.isNotEmpty(string)) {
            if (lawyerUserDto.getMsgCode().equals(string)) {
                LawyerUser lawyerUser = lawyerUserMapper.selectOne(new LambdaQueryWrapper<LawyerUser>()
                        .eq(LawyerUser::getPhone, lawyerUserDto.getPhone()));
                LawyerUserVo vo = new LawyerUserVo();
                if (ObjectUtils.isNotEmpty(lawyerUser)) {
                    LawyerUser update = new LawyerUser();
                    update.setId(lawyerUser.getId());
                    update.setPassword(lawyerUserDto.getPassword());
                    lawyerUserMapper.updateById(update);
                }
                return R.data(ObjectUtils.isNotEmpty(lawyerUser) ? vo : "null");
            }else {
                return R.fail("验证码错误，请重新输入");
            }
        }else {
            return R.fail("验证码已过期");
        }
    }

    @Override
    public Boolean checkRegister(LawyerUserDto lawyerUserDto) {
        LambdaQueryWrapper<LawyerUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LawyerUser::getPhone, lawyerUserDto.getPhone());
        queryWrapper.in(LawyerUser::getStatus, 1);
        queryWrapper.notIn(LawyerUser::getLogoutFlag, 1);
        queryWrapper.eq(LawyerUser::getDeleteFlag, 0);
        List<LawyerUser> lawyerUsers = lawyerUserMapper.selectList(queryWrapper);
        return CollectionUtils.isEmpty(lawyerUsers) ? Boolean.TRUE : Boolean.FALSE;
    }

}
