package cn.newfeifan.mall.module.distri.service.usersigninlog;

import cn.newfeifan.mall.module.distri.controller.app.orderpercentage.vo.OrderPercentageRedisVO;
import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogPageReqVO;
import cn.newfeifan.mall.module.distri.controller.app.usersigninlog.vo.UserSignInLogSaveReqVO;
import cn.newfeifan.mall.module.distri.dal.dataobject.orderpercentage.OrderPercentageDO;
import cn.newfeifan.mall.module.distri.enums.SocialStatusEnum;
import cn.newfeifan.mall.module.distri.service.duser.DuserService;
import cn.newfeifan.mall.module.distri.service.orderpercentage.OrderPercentageService;
import cn.newfeifan.mall.module.distri.service.socialstatus.SocialStatusService;
import cn.newfeifan.mall.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO;
import cn.newfeifan.mall.module.member.convert.signin.MemberSignInRecordConvert;
import cn.newfeifan.mall.module.member.dal.dataobject.signin.MemberSignInRecordDO;
import cn.newfeifan.mall.module.member.service.signin.MemberSignInRecordService;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import cn.newfeifan.mall.module.distri.dal.dataobject.usersigninlog.UserSignInLogDO;
import cn.newfeifan.mall.framework.common.pojo.PageResult;
import cn.newfeifan.mall.framework.common.util.object.BeanUtils;

import cn.newfeifan.mall.module.distri.dal.mysql.usersigninlog.UserSignInLogMapper;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.newfeifan.mall.module.distri.constant.DistriConstants.*;
import static cn.newfeifan.mall.module.distri.enums.ErrorCodeConstants.*;
import static cn.newfeifan.mall.module.member.enums.DictTypeConstants.DISTRI_ORDER_PERCENTAGE;

/**
 * 用户签到日志 Service 实现类
 *
 * @author 非繁人
 */
@Service
@Validated
public class UserSignInLogServiceImpl implements UserSignInLogService {

    @Resource
    private UserSignInLogMapper userSignInLogMapper;

    @Resource
    private MemberSignInRecordService signInRecordService;

    @Resource
    private DuserService duserService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SocialStatusService socialStatusService;

    @Resource
    private OrderPercentageService orderPercentageService;

    @Override
    @Transactional
    public AppMemberSignInRecordRespVO createUserSignInLog() {
        //用户签到
        Long loginUserId = getLoginUserId();
        MemberSignInRecordDO recordDO = signInRecordService.createSignRecord(loginUserId);

        // 插入用户签到日志
        UserSignInLogDO userSignInLogDO = userSignInLogMapper.selectByUserId(loginUserId);
        if (userSignInLogDO == null) {
            //代表还没有过签到记录
            userSignInLogDO = UserSignInLogDO
                    .builder()
                    .userId(loginUserId)
                    .runningDays(DEFAULT_DAY)
                    .build();

            userSignInLogMapper.insert(userSignInLogDO);
        } else {
            //如果是昨天签到过
            if (isTargetYesterday(userSignInLogDO.getUpdateTime())) {
                userSignInLogDO.setRunningDays(userSignInLogDO.getRunningDays() + ONE_DAY);
            } else {
                userSignInLogDO.setRunningDays(DEFAULT_DAY);
            }

            userSignInLogDO.setUpdateTime(LocalDateTime.now());
            userSignInLogMapper.updateById(userSignInLogDO);
        }

        //计算用户签到获得身价
        OrderPercentageRedisVO orderPercentageRedisVO = getOrderPercentageRedisVO();
        long social = Long.parseLong(orderPercentageRedisVO.getSignInSocialStatus());

        if (userSignInLogDO.getRunningDays() >= Integer.parseInt(orderPercentageRedisVO.getSignInSocialStatusMax())) {
            social = social + Long.parseLong(orderPercentageRedisVO.getSignInSocialStatusMax());
        } else {
            social = social + userSignInLogDO.getRunningDays();
        }

        //更新前用户身价等级
        Long socialStatusIdNow = duserService.getDuserByUser(loginUserId).getSocialStatusId();
        //更新用户身价
        duserService.updateDuserSocial(loginUserId, social, SocialStatusEnum.SIGN_IN_SOCIAL.getStatus());

        //更新后用户身价等级
        Long socialStatusIdAfter = duserService.getDuserByUser(loginUserId).getSocialStatusId();

        //判断是否升级
        boolean upgradeOrNot = !socialStatusIdNow.equals(socialStatusIdAfter);
        String socialStatusName = null;
        if (upgradeOrNot) {
            socialStatusName = socialStatusService.getSocialStatusName(socialStatusIdAfter);
        }
        // 返回
        return MemberSignInRecordConvert.INSTANCE.coverRecordToAppRecordVo(recordDO, upgradeOrNot, social, socialStatusName);
    }

    /**
     * 获取身价固定值
     *
     * @return 签到身价固定值
     */
    private OrderPercentageRedisVO getOrderPercentageRedisVO() {
        String s = stringRedisTemplate.opsForValue().get(DISTRI_ORDER_PERCENTAGE);
        if (StringUtils.isEmpty(s)) {
            OrderPercentageDO orderPercentageDO = orderPercentageService.queryStatus();
            OrderPercentageRedisVO signSocial = OrderPercentageRedisVO.builder()
                    .signInSocialStatus(orderPercentageDO.getSignInSocialStatus())
                    .signInSocialStatusMax(orderPercentageDO.getSignInSocialStatusMax())
                    .build();
            stringRedisTemplate.opsForValue().set(DISTRI_ORDER_PERCENTAGE, JSONObject.toJSONString(signSocial));
            s = JSONObject.toJSONString(signSocial);
        }
        return JSONObject.parseObject(s, OrderPercentageRedisVO.class);
    }

    /**
     * 判断给定的LocalDateTime是否为昨天
     *
     * @param targetTime 目标时间
     * @return 如果目标时间是昨天，返回true；否则返回false
     */
    private boolean isTargetYesterday(LocalDateTime targetTime) {
        // 获取当前系统时间的LocalDateTime
        LocalDateTime now = LocalDateTime.now();

        // 获取参考时间的ZonedDateTime，用于处理时区
        ZonedDateTime referenceZonedDateTime = now.atZone(ZoneId.systemDefault());

        // 获取目标时间的ZonedDateTime
        ZonedDateTime targetZonedDateTime = targetTime.atZone(ZoneId.systemDefault());

        // 计算两个时间之间的差值
        long daysDiff = ChronoUnit.DAYS.between(referenceZonedDateTime.toLocalDate(), targetZonedDateTime.toLocalDate());

        return daysDiff == -1; // 如果差值是-1，说明目标时间是昨天
    }

    @Override
    public void updateUserSignInLog(UserSignInLogSaveReqVO updateReqVO) {
        // 校验存在
        validateUserSignInLogExists(updateReqVO.getId());
        // 更新
        UserSignInLogDO updateObj = BeanUtils.toBean(updateReqVO, UserSignInLogDO.class);
        userSignInLogMapper.updateById(updateObj);
    }

    @Override
    public void deleteUserSignInLog(Long id) {
        // 校验存在
        validateUserSignInLogExists(id);
        // 删除
        userSignInLogMapper.deleteById(id);
    }

    private void validateUserSignInLogExists(Long id) {
        if (userSignInLogMapper.selectById(id) == null) {
            throw exception(USER_SIGN_IN_LOG_NOT_EXISTS);
        }
    }

    @Override
    public UserSignInLogDO getUserSignInLog(Long id) {
        return userSignInLogMapper.selectById(id);
    }

    @Override
    public PageResult<UserSignInLogDO> getUserSignInLogPage(UserSignInLogPageReqVO pageReqVO) {
        return userSignInLogMapper.selectPage(pageReqVO);
    }

}
