package com.reyun.saas.mob.user.service.impl;

import com.reyun.saas.common.constants.RoleEnumType;
import com.reyun.saas.common.model.Constant;
import com.reyun.saas.common.restResult.PageParam;
import com.reyun.saas.common.restResult.RestResult;
import com.reyun.saas.common.restResult.ResultCode;
import com.reyun.saas.common.restResult.ResultGenerator;
import com.reyun.saas.common.util.CommonUtil;
import com.reyun.saas.mob.user.dao.AppMapper;
import com.reyun.saas.mob.user.dao.ChannelMapper;
import com.reyun.saas.mob.user.dao.UserMapper;
import com.reyun.saas.mob.user.domain.App;
import com.reyun.saas.mob.user.domain.Channel;
import com.reyun.saas.mob.user.domain.User;
import com.reyun.saas.mob.user.service.AuthService;
import com.reyun.saas.mob.user.service.ChannelService;
import com.reyun.saas.mob.util.RoleUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class ChannelServiceImpl implements ChannelService {

    /**
     * 渠道别名
     */
    private static final String CHANNELALIAS = "channelAlias";

    /**
     * 渠道id
     */
    private static final String CHANNELID = "cid";


    @Resource
    private UserMapper userMapper;

    @Resource
    private ChannelMapper channelMapper;

    @Resource
    private AppMapper appMapper;

    @Resource
    private AuthService authservice;



    /**
     * 渠道列表
     * @param map 筛选条件
     * @param loginUserId 当前登录用户id
     * @return
     */
    @Override
    public RestResult list(Map<String, Object> map, Long loginUserId) {

        //获取分页对象
        PageParam pageParam = CommonUtil.getPageParam(map, "DESC", "c.modify_time");
        fieterOrderField(pageParam);

        String channelAlias = (String) map.get("channelAlias"); //渠道别名
        String channelId = (String) map.get("cid"); //渠道id
        String appName = (String) map.get("appName"); //app名称
        String bid = (String) map.get("bid"); //bid
        Boolean isCustomAlias = (Boolean) map.get("isCustomAlias"); //是否修改过别名
        String query = (String) map.get("query"); //搜索字段 渠道别名和应用名称
        //获取用户
        User loginUser = userMapper.selectByPrimaryKey(loginUserId);

        List<App> apps = authservice.getAppByUser(loginUser);
        List<String> appkeys = apps.stream().map(App::getAppkey).collect(Collectors.toList());
         if(CollectionUtils.isEmpty(appkeys)){
            appkeys.add("-1");
        }

        Integer total = channelMapper.findChannelListCount(appkeys,channelAlias,channelId,bid,isCustomAlias,query);

        pageParam.setPage((pageParam.getPage()-1)*pageParam.getSize());
        List<Channel> channels =
                channelMapper.findChannelList(appkeys,channelAlias,channelId,bid,isCustomAlias,query,pageParam);

        Map<String,Object> result = new LinkedHashMap<>();
        result.put("total",total==null?0:total);
        result.put("list",channels);

        return ResultGenerator.genSuccessResult(result);

    }

    /**
     * 渠道列表无法使用分页插件 需要手动设置排序字段
     */
    private void fieterOrderField(PageParam pageParam){
        String sortOrder = pageParam.getSortOrder();
        String sortField = pageParam.getSortField();
        switch (sortField){
            case "cid":pageParam.setSortField("c.cid");break;
            case "channelAlias" : pageParam.setSortField("c.channel_alias");break;
            case "appName":pageParam.setSortField("a.app_name");break;
            case "bid":pageParam.setSortField("a.bid");break;
            default:pageParam.setSortField("c.modify_time");
        }
        switch (sortOrder){
            case "asc":pageParam.setSortOrder("ASC");break;
            case "desc":pageParam.setSortOrder("DESC");break;
            default:pageParam.setSortOrder("DESC");
        }
    }

    /**
     * bid的筛选条件下拉列表
     * 返回的结果为 " appname | bid " 的样式
     * @param loginUserId 当前登录用户id
     * @return
     */
    @Override
    public RestResult appAndBidScreeningList(Long loginUserId) {

        User loginUser = userMapper.selectByPrimaryKey(loginUserId);

        List<App> apps = authservice.getAppByUser(loginUser);

        List<Map<String, Object>> result = new LinkedList<>();

        if(CollectionUtils.isEmpty(apps)){
            return ResultGenerator.genSuccessResult(result);
        }
        List<String> appkeys = apps.stream().map(App::getAppkey).collect(Collectors.toList());

        List<App> appLinkChannel = appMapper.findAppByAppkeyLinkChannel(appkeys,true);

        if (!CollectionUtils.isEmpty(appLinkChannel)) {
            for (App app : appLinkChannel) {
                String appNameAndBid = app.getAppName() + " | " + app.getBid();
                Map<String, Object> map = new HashMap<>();
                map.put("text", appNameAndBid);
                map.put("value", app.getBid());
                result.add(map);
            }
        }
        return ResultGenerator.genSuccessResult(result);
    }


    /**
     * 其他筛选条件下拉列表
     * @param key 下拉列表类型
     * @param bid 应用包名
     * @param cid 渠道id
     * @param channelAlias  渠道别名
     * @param loginUserId 当前登录用户id
     * @return
     */
    @Override
    public RestResult screeningList(String key, String bid, String cid, String channelAlias, Long loginUserId) {
        if (StringUtils.isEmpty(key)) {
            return ResultGenerator.genResult(ResultCode.PARAMETER_ERROR);
        }
        User loginUser = userMapper.selectByPrimaryKey(loginUserId);

        List<Map<String, Object>> result = new LinkedList<>();

        List<App> apps = authservice.getAppByUser(loginUser);

        if(!StringUtils.isEmpty(bid)){
            apps = apps.stream().filter(v -> v.getBid().equals(bid)).collect(Collectors.toList());
        }

        if(CollectionUtils.isEmpty(apps)){
           return ResultGenerator.genSuccessResult(result);
        }

        List<String> appkeys = apps.stream().map(App::getAppkey).collect(Collectors.toList());


        Example example = new Example(Channel.class);
        example.and().andIn("appkey",appkeys);
        example.and().andEqualTo("delFlag",false);

        if(!StringUtils.isEmpty(cid)){
            example.and().andEqualTo("cid",cid);
        }

        if(!StringUtils.isEmpty(channelAlias)){
            example.and().andEqualTo("channelAlias",channelAlias);
        }

        List<Channel> channels = channelMapper.selectByExample(example);

        if(!CollectionUtils.isEmpty(channels)){
            Set<String> dbStrings = new LinkedHashSet<>();
            for (Channel channel : channels) {
                if (CHANNELALIAS.equals(key)) {
                    dbStrings.add(channel.getChannelAlias());
                } else if (CHANNELID.equals(key)) {
                    dbStrings.add(channel.getCid());
                }
            }

            for (String dbString : dbStrings) {
                Map<String, Object> map = new HashMap<>();
                map.put("text", dbString);
                map.put("value", dbString);
                result.add(map);
            }
        }

        return ResultGenerator.genSuccessResult(result);
    }


    /**
     * 修改用户启用 / 禁用状态
     * @param channelId 渠道id
     * @param loginUserId 当前登录用户id
     * @param status 启用状态  启用: true   禁用false
     * @return
     */
    @Override
    public RestResult updateActiveStatus(Long channelId, Long loginUserId, Boolean status) {
        User user = userMapper.selectByPrimaryKey(loginUserId);

        //校验此次操作的合法性
        if (authservice.checkUserChannelAuth(user,channelId)) {
            return ResultGenerator.genResult(ResultCode.FORBID_OPERATION);
        }

        Channel channel = Channel.builder()
                .id(channelId)
                .active(status)
                .modifyUser(loginUserId)
                .modifyTime(new Date()).build();

        channelMapper.updateByPrimaryKeySelective(channel);
        return ResultGenerator.genSuccessResult();
    }


    /**
     * 修改渠道别名  支持批量修改
     * 修改单个渠道  渠道id参数是size为1的集合
     * @param map 渠道的id (List<Long>)
     * @param loginUserId 当前登录用户id
     * @return
     */
    @Override
    public RestResult updateChannelName(Map<String, Object> map, Long loginUserId) {

        List<Long> cids = (List<Long>) map.get("ids");
        String newChannelName = (String) map.get("newChannelName");

        //校验参数
        if (StringUtils.isEmpty(newChannelName)) {
            return ResultGenerator.genFailResult("渠道别名不能为空!");
        }
        if (CollectionUtils.isEmpty(cids)) {
            return ResultGenerator.genResult(ResultCode.PARAMETER_ERROR);
        }

        User user = userMapper.selectByPrimaryKey(loginUserId);

        //校验当前登陆用户的渠道权限
        List<Channel> channels = authservice.filterUserChannelAuthByChannelId(user, cids);
        if (CollectionUtils.isEmpty(channels)) {
            return ResultGenerator.genResult(ResultCode.FORBID_OPERATION);
        }

        List<Long> channelIds = channels.stream().map(Channel::getId).collect(Collectors.toList());

        Channel channel = new Channel();
        channel.setChannelAlias(newChannelName);
        channel.setModifyTime(new Date());
        channel.setModifyUser(loginUserId);
        channel.setIsCustomAlias(true);

        Example example = new Example(Channel.class);
        example.and().andIn("id",channelIds);
        example.and().andEqualTo("delFlag",false);

        channelMapper.updateByExampleSelective(channel,example);

        return ResultGenerator.genSuccessResult();
    }


    /**
     * 根据appkey查询渠道
     * 目前用于工单中心的创建工单条件的下拉列表
     * @param appkey appkey
     * @param loginUserId 当前登录用户id
     * @return
     */
    @Override
    public RestResult findChannel(String appkey, Long loginUserId) {

        User user = userMapper.selectByPrimaryKey(loginUserId);

        if (!authservice.checkUserAppAuth(user,appkey)) {
            return ResultGenerator.genSuccessResult();
        }

        Example channel = new Example(Channel.class);
        channel.and().andEqualTo("appkey",appkey);
        channel.and().andEqualTo("delFlag",false);
        channel.and().andEqualTo("active",true);
        List<Channel> channels = channelMapper.selectByExample(channel);

        return ResultGenerator.genSuccessResult(channels);
    }

    @Override
    public List<Map<String, Object>> findChannelsByAppkey(Long loginUserId, String appkey, String os) {
        os = os.equals("1")?Constant.OS_IOS:Constant.OS_ANDROID;
        User loginUser = userMapper.selectByPrimaryKey(loginUserId);
        List<Map<String, Object>> channels = null;

        if(RoleUtil.isSuperUserOrManager(loginUser) || RoleEnumType.SUB_APP_MANAGER.getKey().equals(loginUser.getRoleCategory())){
            //主账号 管理员  子应用管理员 根据app权限查询渠道

            //appkey为空  查询用户对应os的所有渠道
            if(StringUtils.isEmpty(appkey)){
                List<App> apps = authservice.getAppByUserAndOs(loginUser,os,false);
                if(CollectionUtils.isEmpty(apps)){
                    return channels;
                }
                List<String> appkeys = apps.stream().map(App::getAppkey).collect(Collectors.toList());
                channels = channelMapper.findByappkeysAndIsActive(appkeys);
            }else{
                //appkey不为空

                //校验合法性
                if (!authservice.checkUserAppAuth(loginUser,appkey)) {
                    return channels;
                }

                Example example = new Example(App.class);
                example.and().andEqualTo("appkey",appkey);
                example.and().andEqualTo("delFlag",false);
                example.and().andEqualTo("disableFlag",false);
                App app = appMapper.selectOneByExample(example);
                if(app == null){
                    return channels;
                }
                List<String> appkeys = new ArrayList<>();
                appkeys.add(app.getAppkey());
                channels = channelMapper.findByappkeysAndIsActive(appkeys);
            }
        }else{
            //其他角色
        }

        return channels;
    }


}
