package com.wecloud.im.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.mapper.ImClientMapper;
import com.wecloud.im.param.GetClientInfoParam;
import com.wecloud.im.param.ImClientPageParam;
import com.wecloud.im.param.ImClientQueryVo;
import com.wecloud.im.param.add.ImClientDeviceInfoAdd;
import com.wecloud.im.param.add.ImClientHeadPortraitAdd;
import com.wecloud.im.param.add.ImClientNicknameAdd;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.vo.GetInfoListVo;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 终端表 服务实现类
 *
 * @author wei
 * @since 2021-04-27
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "client")
public class ImClientServiceImpl extends BaseServiceImpl<ImClientMapper, ImClient> implements ImClientService {

    @Autowired
    private ImClientMapper imClientMapper;
    @Autowired
    private ImApplicationService imApplicationService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateHeadPortrait(ImClientHeadPortraitAdd imClientHeadPortraitAdd) throws Exception {
        ImClient curentClient = getCurentClient();

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询appid
//        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());


        curentClient.setHeadPortrait(imClientHeadPortraitAdd.getHeadPortrait());
        imClientMapper.updateById(curentClient);

        // 清除client的redis缓存
        deleteCacheImClient(curentClient.getFkAppid(), curentClient.getClientId());

        return true;
    }

    @Override
    public ApiResult<List<GetInfoListVo>> getInfoList(GetClientInfoParam getClientInfoParam) throws Exception {
        ImClient curentClient = getCurentClient();

//        List<ImClient> imClients = this.list(new QueryWrapper<ImClient>().lambda()
//                .eq(ImClient::getFkAppid, curentClient.getFkAppid())
//                .in(ImClient::getClientId, getClientInfoParam.getClientId())
//        );
//
//        List<GetInfoListVo> getInfoListVos = new ArrayList<>();
//
//        for (ImClient imClient : imClients) {
//
//            GetInfoListVo getInfoListVo = new GetInfoListVo();
//            getInfoListVo.setHeadPortrait(imClient.getHeadPortrait());
//            getInfoListVo.setNickname(imClient.getNickname());
//            getInfoListVo.setClientId(imClient.getClientId());
//            getInfoListVos.add(getInfoListVo);
//        }

        List<GetInfoListVo> infoList = imClientMapper.getInfoList(curentClient.getFkAppid(), getClientInfoParam.getConversationId(), getClientInfoParam.getClientIds());

        return ApiResult.ok(infoList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateNickname(ImClientNicknameAdd imClientNicknameAdd) throws Exception {
        ImClient curentClient = getCurentClient();

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询appid
//        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());


        curentClient.setNickname(imClientNicknameAdd.getNickname());
        imClientMapper.updateById(curentClient);

        // 清除client的redis缓存
        deleteCacheImClient(curentClient.getFkAppid(), curentClient.getClientId());

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveImClient(ImClient imClient) throws Exception {
        return super.save(imClient);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDeviceInfo(ImClientDeviceInfoAdd imClientDevice) {

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询appid
        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());

        // 清除旧client的redis缓存
        ImClient imClient = this.getOne(new QueryWrapper<ImClient>().lambda()
                .eq(ImClient::getFkAppid, imApplication.getId())
                .eq(ImClient::getDeviceToken, imClientDevice.getDeviceToken()));
        if (imClient != null) {
            deleteCacheImClient(imClient.getFkAppid(), imClient.getClientId());
            // client登陆的时候 判断数据库内是否已经存在这个设备token,如果存在就清空旧的
            this.removeOldToken(imApplication.getId(), curentJwtToken.getToken());
        }

        ImClient client = getCurentClient();
        ImClient clientNew = new ImClient();
        BeanUtils.copyProperties(imClientDevice, clientNew);
        clientNew.setId(client.getId());

        // 清除新client的redis缓存
        deleteCacheImClient(client.getFkAppid(), client.getClientId());

        // 修改
        return this.updateImClient(clientNew);
    }

    @Override
    public boolean logout() {

        ImClient curentClient = getCurentClient();

        // 清除设备token
        boolean update = this.update(new UpdateWrapper<ImClient>().lambda()
                .eq(ImClient::getFkAppid, curentClient.getFkAppid())
                .eq(ImClient::getId, curentClient.getId())
                .set(ImClient::getDeviceToken, null)
        );
        if (update) {
            // 清除新client的redis缓存
            deleteCacheImClient(curentClient.getFkAppid(), curentClient.getClientId());
        }

        return update;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateImClient(ImClient imClient) {
        return super.updateById(imClient);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteImClient(Long id) throws Exception {
        return super.removeById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int removeOldToken(Long appId, String deviceToken) {

        return imClientMapper.removeOldToken(appId, deviceToken);
    }

    @Override
    public ImClientQueryVo getImClientById(Long id) throws Exception {
        return imClientMapper.getImClientById(id);
    }

    @Override
    public Paging<ImClientQueryVo> getImClientPageList(ImClientPageParam imClientPageParam) throws Exception {
        Page<ImClientQueryVo> page = new PageInfo<>(imClientPageParam, OrderItem.desc(getLambdaColumn(ImClient::getCreateTime)));
        IPage<ImClientQueryVo> iPage = imClientMapper.getImClientPageList(page, imClientPageParam);
        return new Paging<>(iPage);
    }

    @Override
    public ImClient getCurentClient() {

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询appid
        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());
        return getCacheImClient(imApplication.getId(), curentJwtToken.getClientId());
    }

    @Override
    @Cacheable(key = "#p0+#p1")
    public ImClient getCacheImClient(Long applicationId, String clientId) {
        return this.getOne(new QueryWrapper<ImClient>().lambda()
                .eq(ImClient::getFkAppid, applicationId)
                .eq(ImClient::getClientId, clientId));
    }

    @Override
    @CacheEvict(key = "#p0+#p1")
    public void deleteCacheImClient(Long applicationId, String clientId) {
    }

}
