package com.ym.mec.biz.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.ImLiveRoomPurviewDao;
import com.ym.mec.biz.dal.dto.SysUserDto;
import com.ym.mec.biz.dal.entity.ImGroup;
import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
import com.ym.mec.biz.dal.entity.ImLiveRoomPurview;
import com.ym.mec.biz.dal.entity.Student;
import com.ym.mec.biz.dal.enums.TemplateTypeEnum;
import com.ym.mec.biz.service.ImLiveBroadcastRoomService;
import com.ym.mec.biz.service.ImLiveRoomPurviewService;
import com.ym.mec.biz.service.StudentService;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.page.PageUtil;
import com.ym.mec.common.page.WrapperUtil;
import com.ym.mec.common.tenant.TenantContextHolder;
import com.ym.mec.util.excel.POIUtil;
import com.ym.mec.util.ini.IniFileUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 直播间的观看权限表(ImLiveRoomPurview)表服务实现类
 *
 * @author hgw
 * @since 2022-06-08 09:43:48
 */
@Service("imLiveRoomPurviewService")
public class ImLiveRoomPurviewServiceImpl extends ServiceImpl<ImLiveRoomPurviewDao, ImLiveRoomPurview> implements ImLiveRoomPurviewService {

    private final static Logger log = LoggerFactory.getLogger(ImLiveRoomPurviewServiceImpl.class);

    @Autowired
    private StudentService studentService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private ImLiveBroadcastRoomService imLiveBroadcastRoomService;

    public ImLiveRoomPurviewDao getDao() {
        return this.baseMapper;
    }

    /**
     * 批量添加/根据查询条件添加房间观看权限
     *
     * @param param 参数
     *              <p> - search 搜索关键字
     *              <p> - subjectId 声部ID
     *              <p> - organIds 分部ID
     *              <p> - groupIds 群聊ID
     *              <p> - teamIds 乐团ID
     *              <p> - schoolIds 学校id/合作单位id
     *              <p> - roomUid 直播间UID
     */
    public void addByCondition(Map<String, Object> param) {
        String roomUid = WrapperUtil.toStr(param, "roomUid", "房间uid不能为空");
        param.put("tenantId", TenantContextHolder.getTenantId());
        //必需有一个参数条件，要不然数据太多了
        this.checkParam(param, "search", "subjectId", "organIds", "groupIds", "teamIds", "schoolIds");
        //根据条件查询学员
        List<SysUserDto> studentList = baseMapper.selectRoomPurviewStudent(param);
        if (CollectionUtils.isEmpty(studentList)) {
            throw new BizException("没有查询到人员信息");
        }
        Stream<Integer> userIdList = studentList.stream().map(SysUserDto::getUserId).map(Long::intValue);
        //添加学员
        batchStudentInsert(userIdList, roomUid);
    }

    /**
     * 校验条件，必需有一个参数条件
     *
     * @param param 参数
     * @param keys  参数key
     */
    private void checkParam(Map<String, Object> param, String... keys) {
        boolean checkVal = false;
        for (String key : keys) {
            String val = WrapperUtil.toStr(param, key);
            if (StringUtils.isNotBlank(val)) {
                checkVal = true;
            }
        }
        if(!checkVal){
            throw new BizException("必需要有一个查询条件");
        }
    }

    /**
     * 指定多个学员id添加观看权限数据
     *
     * @param ids     bizId
     * @param roomUid 直播间UID
     */
    @Override
    public void add(String ids, String roomUid) {
        Optional.ofNullable(roomUid).orElseThrow(() -> new BizException("房间uid不能为空"));
        Optional.ofNullable(ids)
                .filter(WrapperUtil.StrPredicate)
                .orElseThrow(() -> new BizException("请选择要删除的数据"));
        //查询房间类型
        ImLiveBroadcastRoom room = imLiveBroadcastRoomService.getOne(Wrappers.<ImLiveBroadcastRoom>lambdaQuery()
                .eq(ImLiveBroadcastRoom::getRoomUid, roomUid));
        if (Objects.isNull(room)) {
            throw new BizException("房间不存在");
        }
        if (Objects.nonNull(room.getPopularizeType()) && Objects.equals(room.getPopularizeType(), ImLiveBroadcastRoom.ALL)) {
            throw new BizException("该直播间为公开类型的直播间，不能添加观看权限");
        }
        //添加学员
        List<Integer> userIdList = WrapperUtil.splitToIntList(ids);
        if (CollectionUtils.isEmpty(userIdList)) {
            return;
        }
        batchStudentInsert(userIdList.stream(), roomUid);
    }

    private void batchStudentInsert(Stream<Integer> stream, String roomUid) {
        if (Objects.isNull(stream)) {
            return;
        }
        Date date = new Date();
        Integer userId = getSysUser().getId();
        List<ImLiveRoomPurview> collect = stream.map(id -> {
            ImLiveRoomPurview imLiveRoomPurview = new ImLiveRoomPurview();
            imLiveRoomPurview.setRoomUid(roomUid);
            imLiveRoomPurview.setUserId(id);
            imLiveRoomPurview.setType("STUDENT");
            imLiveRoomPurview.setCreatedBy(userId);
            imLiveRoomPurview.setCreatedTime(date);
            return imLiveRoomPurview;
        }).collect(Collectors.toList());
        Lists.partition(collect, 100).forEach(l -> baseMapper.insertBatch(l));
    }

    /**
     * 删除观看权限数据
     *
     * @param ids     bizId
     * @param roomUid 直播间UID
     */
    @Override
    public void delete(String ids, String roomUid) {
        Optional.ofNullable(roomUid).orElseThrow(() -> new BizException("房间uid不能为空"));
        Optional.ofNullable(ids).orElseThrow(() -> new BizException("请选择要删除的数据"));
        List<Integer> userIdList = WrapperUtil.splitToIntList(ids);
        this.remove(Wrappers.<ImLiveRoomPurview>lambdaQuery()
                .in(ImLiveRoomPurview::getUserId, userIdList)
                .eq(ImLiveRoomPurview::getRoomUid, roomUid));
    }

    /**
     * 查询学员列表-观看权限
     *
     * @param param 参数
     *              <p> - search 搜索关键字
     *              <p> - subjectId 声部ID
     *              <p> - organIds 分部ID
     *              <p> - groupIds 群聊ID
     *              <p> - teamIds 乐团ID
     *              <p> - schoolIds 学校id/合作单位id
     *              <p> - roomUid 直播间UID
     *              <p> -page 页数
     *              <p> -rows 每页数量
     */
    @Override
    public PageInfo<SysUserDto> queryStudent(Map<String, Object> param) {
        WrapperUtil.toStr(param, "roomUid", "房间uid不能为空");
        param.put("inExist", 1);
        param.put("tenantId", TenantContextHolder.getTenantId());
        Page<SysUserDto> pageInfo = PageUtil.getPageInfo(param);
        return PageUtil.pageInfo(baseMapper.selectRoomPurviewStudent(pageInfo, param));
    }

    /**
     * 选择-观看权限-查询学员列表
     *
     * @param param 参数
     *              <p> - search 搜索关键字
     *              <p> - subjectId 声部ID
     *              <p> - organIds 分部ID
     *              <p> - groupIds 群聊ID
     *              <p> - teamIds 乐团ID
     *              <p> - schoolIds 学校id/合作单位id
     *              <p> - roomUid 直播间UID
     *              <p> -page 页数
     *              <p> -rows 每页数量
     */
    @Override
    public PageInfo<SysUserDto> selectRoomPurviewStudent(Map<String, Object> param) {
        WrapperUtil.toStr(param, "roomUid", "房间uid不能为空");
        param.put("tenantId", TenantContextHolder.getTenantId());
        Page<SysUserDto> pageInfo = PageUtil.getPageInfo(param);
        return PageUtil.pageInfo(baseMapper.selectRoomPurviewStudent(pageInfo, param));
    }

    /**
     * 选择-观看权限-群聊列表
     *
     * @param param 参数
     *              <p> - search 搜索关键字
     *              <p> - roomUid 直播间UID
     *              <p> - groupType 群类型
     */
    @Override
    public PageInfo<ImGroup> selectRoomPurviewGroup(Map<String, Object> param) {
        //查询当前登录人分部
        SysUser sysUser = getSysUser();
        param.put("userId", sysUser.getId());
        Page<ImGroup> pageInfo = PageUtil.getPageInfo(param);
        return PageUtil.pageInfo(baseMapper.selectRoomPurviewGroup(pageInfo, param));
    }

    /**
     * 导入观看权限-人员n
     */
    @Override
    public String importPurviewUser(MultipartFile file, String roomUid) throws Exception {
        Map<String, List<Map<String, Object>>> sheetsListMap = POIUtil.importExcel(
                new ByteArrayInputStream(file.getBytes()), 0, file.getOriginalFilename());
        InputStream inputStream = new ClassPathResource("columnMapper.ini").getInputStream();
        Map<String, String> columns = IniFileUtil.readIniFile(inputStream, TemplateTypeEnum.LIVE_ROOM_PURVIEW_USER.getMsg());
        List<Integer> userIdList = new ArrayList<>();
        Map<Integer, Object> userIdMap = new HashMap<>();
        Integer id = getSysUser().getId();
        Date now = new Date();
        Integer tenantId = TenantContextHolder.getTenantId();
        for (String e : sheetsListMap.keySet()) {
            List<Map<String, Object>> sheet = sheetsListMap.get(e);
            for (Map<String, Object> row : sheet) {
                if (row.size() == 0) {
                    continue;
                }
                for (String s : row.keySet()) {
                    if (!columns.containsKey(s)) {
                        continue;
                    }
                    if (columns.get(s).equals("userId")) {
                        if (null == row.get(s) || StringUtils.isBlank(row.get(s).toString())) {
                            log.error("导入异常：{}不可为空", s);
                            continue;
                        }
                        Integer userId = Integer.valueOf(row.get(s).toString());
                        if (Objects.nonNull(userIdMap.get(userId))) {
                            continue;
                        }
                        Student student = studentService.get(userId);
                        if (Objects.isNull(student)) {
                            throw new BizException("导入异常：编号 " + userId + " 的用户不存在");
                        }
                        if (!Objects.equals(student.getTenantId(), tenantId)) {
                            throw new BizException("导入异常：编号 " + userId + " 的用户不是该机构的学员");
                        }
                        userIdList.add(userId);
                        userIdMap.put(userId, userId);
                    }
                }
            }
        }
        try {
            userIdList = userIdList.stream().distinct().collect(Collectors.toList());
            List<ImLiveRoomPurview> purviewList = userIdList.stream()
                    .map(userId -> {
                        ImLiveRoomPurview obj = new ImLiveRoomPurview();
                        obj.setUserId(userId);
                        obj.setRoomUid(roomUid);
                        obj.setType("STUDENT");
                        obj.setCreatedBy(id);
                        obj.setCreatedTime(now);
                        return obj;
                    }).collect(Collectors.toList());
            Lists.partition(purviewList, 100).forEach(list -> baseMapper.insertBatch(list));
        } catch (Exception ex) {
            throw new BizException("导入数据出错:" + ex, ex);
        }
        return "成功导入 " + userIdList.size() + "条";
    }

    private SysUser getSysUser() {
        //修改机构基础信息
        return Optional.ofNullable(sysUserFeignService.queryUserInfo())
                .orElseThrow(() -> new BizException("用户不存在."));
    }
}

