package com.yonge.cooleshow.biz.dal.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.entity.PianoRoomTime;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.InOrOutEnum;
import com.yonge.cooleshow.biz.dal.enums.MessageTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
import com.yonge.cooleshow.biz.dal.service.PianoRoomTimeService;
import com.yonge.cooleshow.biz.dal.service.SysMessageService;
import com.yonge.cooleshow.common.enums.CacheNameEnum;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.payment.util.DistributedLock;
import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yonge.cooleshow.biz.dal.entity.PianoRoomChangeRecord;
import com.yonge.cooleshow.biz.dal.vo.PianoRoomChangeRecordVo;
import com.yonge.cooleshow.biz.dal.dto.search.PianoRoomChangeRecordSearch;
import com.yonge.cooleshow.biz.dal.dao.PianoRoomChangeRecordDao;
import com.yonge.cooleshow.biz.dal.service.PianoRoomChangeRecordService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Service
public class PianoRoomChangeRecordServiceImpl extends ServiceImpl<PianoRoomChangeRecordDao, PianoRoomChangeRecord> implements PianoRoomChangeRecordService {
    private final static Logger log = LoggerFactory.getLogger(PianoRoomChangeRecordServiceImpl.class);
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private PianoRoomTimeService pianoRoomTimeService;
    @Resource
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private SysMessageService sysMessageService;

    @Override
    public PianoRoomChangeRecordVo detail(Long id) {
        return baseMapper.detail(id);
    }

    @Override
    public IPage<PianoRoomChangeRecordVo> selectPage(IPage<PianoRoomChangeRecordVo> page, PianoRoomChangeRecordSearch query) {
        return page.setRecords(baseMapper.selectPage(page, query));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean add(PianoRoomChangeRecord pianoRoomChangeRecord) {
        //保存记录
        save(pianoRoomChangeRecord);
        //入琴房账户
        setPianoRoomTime(pianoRoomChangeRecord.getUserId(), pianoRoomChangeRecord.getTimes(), pianoRoomChangeRecord.getInOrOut());
        //琴房推送
        sendMessage(pianoRoomChangeRecord);
        return true;
    }

    /**
     * 增/减老师琴房课时长
     *
     * @param userId 老师id
     * @param times 时长
     * @param inOrOut 增/减
     */
    private void setPianoRoomTime(Long userId, Integer times, InOrOutEnum inOrOut) {
        DistributedLock.of(redissonClient)
                       .runIfLockToFunction(CacheNameEnum.LOCK_CHANGE_PIANO_ROOM_ACCOUNT.getRedisKey(userId)
                               , (o) -> {
                                        PianoRoomTime pianoRoomTime = pianoRoomTimeService.getOne(Wrappers.<PianoRoomTime>lambdaQuery()
                                                .eq(PianoRoomTime::getTeacherId, userId));

                                        if (null == pianoRoomTime) {
                                            pianoRoomTime = new PianoRoomTime();
                                            pianoRoomTime.setRemainTime(0);
                                            pianoRoomTime.setFrozenTime(0);
                                            pianoRoomTime.setTeacherId(userId);
                                            pianoRoomTimeService.save(pianoRoomTime);
                                        }

                                        if (InOrOutEnum.IN.equals(inOrOut)) {
                                            pianoRoomTime.setRemainTime(pianoRoomTime.getRemainTime() + times);
                                        } else {
                                            pianoRoomTime.setRemainTime(pianoRoomTime.getRemainTime() - times);
                                        }

                                        if (pianoRoomTime.getRemainTime() < 0) {
                                            throw new BizException("扣除时长超过老师可用时长");
                                        }
                                        pianoRoomTime.setUpdateTime(new Date());
                                        pianoRoomTimeService.updateById(pianoRoomTime);
                                        return null;
                               }, null, 10l);
    }


    private void sendMessage(PianoRoomChangeRecord record) {
        // 发送课程下架通知
        try {
            SysUser user = sysUserFeignService.queryUserById(record.getUserId());
            Map<Long, String> receivers = new HashMap<>();
            receivers.put(user.getId(), user.getPhone());
            if(InOrOutEnum.IN.equals(record.getInOrOut())){
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.PIANO_ROOM_TIMES_ADD,
                        receivers, null, 0, null, ClientEnum.TEACHER.getCode(),
                        record.getTimes(), record.getReason());
            }else if(InOrOutEnum.OUT.equals(record.getInOrOut())){
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.PIANO_ROOM_TIMES_SUB,
                        receivers, null, 0, null, ClientEnum.TEACHER.getCode(),
                        record.getTimes(), record.getReason());
            }
        } catch (Exception e) {
            log.warn("视频课下架推送发送失败，{}", e.getMessage());
        }
    }

}