package com.tzld.piaoquan.growth.common.service.Impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tzld.piaoquan.growth.common.common.base.CommonResponse;
import com.tzld.piaoquan.growth.common.common.enums.PreSpecialStatusEnum;
import com.tzld.piaoquan.growth.common.component.HttpPoolClient;
import com.tzld.piaoquan.growth.common.component.ProxyHttpPoolClient;
import com.tzld.piaoquan.growth.common.dao.mapper.*;
import com.tzld.piaoquan.growth.common.dao.mapper.ext.WeComUserMapperExt;
import com.tzld.piaoquan.growth.common.model.bo.GroupSendWeComUserParam;
import com.tzld.piaoquan.growth.common.model.bo.WeComUserBo;
import com.tzld.piaoquan.growth.common.model.po.*;
import com.tzld.piaoquan.growth.common.model.vo.UserTagParam;
import com.tzld.piaoquan.growth.common.model.vo.WeComUserVo;
import com.tzld.piaoquan.growth.common.service.WeComAccessTokenService;
import com.tzld.piaoquan.growth.common.service.WeComSendService;
import com.tzld.piaoquan.growth.common.service.WeComUserService;
import com.tzld.piaoquan.growth.common.utils.DateUtil;
import com.tzld.piaoquan.growth.common.utils.LarkRobotUtil;
import com.tzld.piaoquan.growth.common.utils.page.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.tzld.piaoquan.growth.common.common.constant.RedisConstant.WE_COM_USER_AB_TYPE;
import static com.tzld.piaoquan.growth.common.common.constant.WeComConstant.GET_WE_COM_EXTERNAL_CONTACT_GET;
import static com.tzld.piaoquan.growth.common.common.constant.WeComConstant.POST_WE_COM_ADD_USER_TAG;

@Slf4j
@Service
public class WeComUserServiceImpl implements WeComUserService {
    @Autowired
    private HttpPoolClient httpPoolClient;

    @Autowired
    private ProxyHttpPoolClient proxyHttpPoolClient;

    @Autowired
    private WeComAccessTokenService weComAccessTokenService;

    @Autowired
    private WeComUserMapper weComUserMapper;

    @Autowired
    private WeComUserMapperExt weComUserMapperExt;

    @Autowired
    private StaffWithUserMapper staffWithUserMapper;

    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private UserWithTagMapper userWithTagMapper;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Value("${needFilterTagIdConfig:[]}")
    private String needFilterTagIdConfig;



    @Override
    public void addStaffWithUser(String externalUserId, String carrierId, Long corpId) {
        if (StringUtils.isEmpty(externalUserId) || StringUtils.isEmpty(carrierId)) {
            return;
        }
        Staff staff = getStaff(carrierId, corpId);
        insertStaffWithUser(externalUserId, staff, corpId);
    }

    @Override
    public void insertStaffWithUser(String externalUserId, Staff staff, Long corpId) {
        try {
            WeComUserExample weComUserExample = new WeComUserExample();
            weComUserExample.createCriteria().andExternalUserIdEqualTo(externalUserId);
            List<WeComUser> weComUserList = weComUserMapper.selectByExample(weComUserExample);
            if (CollectionUtils.isEmpty(weComUserList)) {
                JSONObject userDetail = getUserDetail(externalUserId, corpId);
                if (userDetail == null) {
                    return;
                }
                JSONObject externalContact = userDetail.getJSONObject("external_contact");
                JSONArray followUserList = userDetail.getJSONArray("follow_user");
                Long createAt = null;
                List<String> staffUserIdList = new ArrayList<>();
                for (int i = 0; i < followUserList.size(); i++) {
                    JSONObject followUser = followUserList.getJSONObject(i);
                    if (createAt == null) {
                        createAt = followUser.getLong("createtime");
                    } else {
                        createAt = Math.min(createAt, followUser.getLong("createtime"));
                    }
                    String userId = followUser.getString("userid");
                    if (StringUtils.isNotEmpty(userId)) {
                        staffUserIdList.add(userId);
                    }
                }
                String name = externalContact.getString("name");
                String unionId = externalContact.getString("unionid");
                String avatar = externalContact.getString("avatar");
                Integer type = externalContact.getInteger("type");
                Integer gender = externalContact.getInteger("gender");
                WeComUser weComUser = new WeComUser();
                weComUser.setExternalUserId(externalUserId);
                weComUser.setCreatedAt(createAt);
                weComUser.setName(name);
                weComUser.setUnionId(unionId);
                weComUser.setAvatar(avatar);
                weComUser.setType(type);
                weComUser.setGender(gender);
                weComUser.setCorpId(corpId);
                Long increment = redisTemplate.opsForValue().increment(WE_COM_USER_AB_TYPE);
                if(increment != null){
                    weComUser.setAbtype("ab" + increment % 10);
                }
                weComUserMapper.insertSelective(weComUser);
                Long userId = weComUser.getId();
                if (userId == null) {
                    log.error("insertStaffWithUserJob insert weComUser error weComUser={}", weComUser);
                    return;
                }
                if (CollectionUtils.isEmpty(staffUserIdList)) {
                    return;
                }
                for (String staffUserId : staffUserIdList) {
                    StaffExample staffExample = new StaffExample();
                    staffExample.createCriteria().andCarrierIdEqualTo(staffUserId);
                    List<Staff> staffList1 = staffMapper.selectByExample(staffExample);
                    if (CollectionUtils.isEmpty(staffList1)) {
                        continue;
                    }
                    Staff staff1 = staffList1.get(0);
                    Long staffId = staff1.getId();
                    StaffWithUser staffWithUser = new StaffWithUser();
                    staffWithUser.setStaffId(staffId);
                    staffWithUser.setUserId(userId);
                    staffWithUserMapper.insertSelective(staffWithUser);
                }
            } else {
                WeComUser weComUser = weComUserList.get(0);
                StaffWithUserExample staffWithUserExample = new StaffWithUserExample();
                staffWithUserExample.createCriteria().andUserIdEqualTo(weComUser.getId()).andStaffIdEqualTo(staff.getId());
                List<StaffWithUser> staffWithUserList = staffWithUserMapper.selectByExample(staffWithUserExample);
                if (CollectionUtils.isEmpty(staffWithUserList)) {
                    StaffWithUser staffWithUser = new StaffWithUser();
                    staffWithUser.setStaffId(staff.getId());
                    staffWithUser.setUserId(weComUser.getId());
                    staffWithUserMapper.insertSelective(staffWithUser);
                } else {
                    StaffWithUser staffWithUser = staffWithUserList.get(0);
                    if (staffWithUser.getIsDelete() == 1) {
                        staffWithUser.setIsDelete(0);
                        staffWithUser.setNewIsDelete(0);
                        staffWithUserMapper.updateByPrimaryKeySelective(staffWithUser);
                        Long userId = staffWithUser.getUserId();
                        WeComUser weComUser1 = weComUserMapper.selectByPrimaryKey(userId);
                        if(weComUser1.getIsDelete() == 1){
                            weComUser1.setIsDelete(0);
                            weComUserMapper.updateByPrimaryKeySelective(weComUser1);
                        }
                    }
                }
            }
        } catch (Exception e) {
            LarkRobotUtil.sendMessage("insertUser error externalUserId=" + externalUserId + e);
            log.error("insertUser error", e);
        }
    }

    @Override
    public void delStaffWithUser(String externalUserId, String carrierId, Long corpId, Long deleteTime) {
        if (StringUtils.isEmpty(externalUserId) || StringUtils.isEmpty(carrierId)) {
            return;
        }
        Staff staff = getStaff(carrierId, corpId);
        if (staff == null) {
            return;
        }
        WeComUser weComUser = getUser(externalUserId);
        if (weComUser == null) {
            return;
        }
        StaffWithUserExample example = new StaffWithUserExample();
        example.createCriteria().andStaffIdEqualTo(staff.getId()).andUserIdEqualTo(weComUser.getId());
        List<StaffWithUser> staffWithUserList = staffWithUserMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(staffWithUserList) || staffWithUserList.get(0).getIsDelete() == 1) {
            return;
        }
        StaffWithUser staffWithUser = staffWithUserList.get(0);
        staffWithUser.setDeleteTime(new Date());
        staffWithUser.setIsDelete(1);
        staffWithUserMapper.updateByPrimaryKeySelective(staffWithUser);
        StaffWithUserExample staffWithUserExample = new StaffWithUserExample();
        staffWithUserExample.createCriteria().andUserIdEqualTo(weComUser.getId()).andIsDeleteEqualTo(0);
        long l = staffWithUserMapper.countByExample(staffWithUserExample);
        if (l == 0) {
            Long userId = staffWithUser.getUserId();
            WeComUser weComUser1 = weComUserMapper.selectByPrimaryKey(userId);
            if(weComUser1.getIsDelete() == 0){
                weComUser1.setIsDelete(1);
                weComUserMapper.updateByPrimaryKeySelective(weComUser1);
            }
        }
    }

    @Override
    public void delStaffWithUser(Long userId, Long staffId, Long deleteTime) {
        if (userId == null || staffId == null) {
            return;
        }
        StaffWithUserExample example = new StaffWithUserExample();
        example.createCriteria().andStaffIdEqualTo(staffId).andUserIdEqualTo(userId);
        List<StaffWithUser> staffWithUserList = staffWithUserMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(staffWithUserList) || staffWithUserList.get(0).getIsDelete() == 1) {
            return;
        }
        StaffWithUser staffWithUser = staffWithUserList.get(0);
        if (deleteTime != null) {
            staffWithUser.setDeleteTime(new Date(deleteTime));
            staffWithUser.setNewDeleteTime(new Date(deleteTime));
        }else {
            staffWithUser.setNewDeleteTime(new Date());
        }
        staffWithUser.setIsDelete(1);
        staffWithUser.setNewIsDelete(1);
        staffWithUserMapper.updateByPrimaryKeySelective(staffWithUser);
        StaffWithUserExample staffWithUserExample = new StaffWithUserExample();
        staffWithUserExample.createCriteria().andUserIdEqualTo(userId).andIsDeleteEqualTo(0);
        long l = staffWithUserMapper.countByExample(staffWithUserExample);
        if (l == 0) {
            WeComUser weComUser1 = weComUserMapper.selectByPrimaryKey(userId);
            if(weComUser1.getIsDelete() == 0){
                weComUser1.setIsDelete(1);
                weComUserMapper.updateByPrimaryKeySelective(weComUser1);
            }
        }
    }


    private Staff getStaff(String carrierId, Long corpId) {
        StaffExample example = new StaffExample();
        example.createCriteria().andCarrierIdEqualTo(carrierId).andCorpIdEqualTo(corpId);
        List<Staff> staffList = staffMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(staffList)) {
            log.error("getStaff staff empty carrierId={}", carrierId);
            return null;
        }
        return staffList.get(0);
    }

    private WeComUser getUser(String externalUserId) {
        WeComUserExample weComUserExample = new WeComUserExample();
        weComUserExample.createCriteria().andExternalUserIdEqualTo(externalUserId);
        List<WeComUser> weComUserList = weComUserMapper.selectByExample(weComUserExample);
        if (CollectionUtils.isEmpty(weComUserList)) {
            log.error("getUser user empty externalUserId={}", externalUserId);
            return null;
        }
        return weComUserList.get(0);
    }


    public JSONObject getUserDetail(String externalUserId, Long corpId) {
        try {
            String weComAccessToken = weComAccessTokenService.getWeComAccessToken(corpId);
            String url = String.format(GET_WE_COM_EXTERNAL_CONTACT_GET + "?access_token=%s&external_userid=%s", weComAccessToken, externalUserId);
            String res;
            if (corpId == 1L) {
                res = httpPoolClient.get(url);
            } else {
                res = proxyHttpPoolClient.get(url);
            }
            JSONObject jsonObject = JSONObject.parseObject(res);
            Integer errcode = jsonObject.getInteger("errcode");
            if (errcode == 0) {
                return jsonObject;
            }
        } catch (Exception e) {
            log.error("getUserDetail error", e);
        }

        return null;
    }

    @Override
    public List<WeComUserVo> getWeComUserByNameAvatar(String name, String avatar) {
        WeComUserExample example = new WeComUserExample();
        example.createCriteria().andNameEqualTo(name).andAvatarEqualTo(avatar);
        List<WeComUser> list = weComUserMapper.selectByExample(example);
        return buildWeComUserVo(list);
    }

    private List<WeComUserVo> buildWeComUserVo(List<WeComUser> list) {
        List<WeComUserVo> voList = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return voList;
        }
        for (WeComUser weComUser : list) {
            WeComUserVo vo = new WeComUserVo();
            BeanUtils.copyProperties(weComUser, vo);
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public Page<WeComUserVo> getGroupSendWeComUser(GroupSendWeComUserParam param) {
        Date start = DateUtil.getDaysAgoDate(1);
        Date end = DateUtil.getThatDayDate();
        String preSendDate = DateUtil.getBeforeDayDateString(1, "yyyy-MM-dd");
        if (Objects.nonNull(param) && StringUtils.isNotEmpty(param.getDateStr())) {
            start = DateUtil.getDate(param.getDateStr());
            end = DateUtil.getDatePlusDays(param.getDateStr(), 1);
            preSendDate = param.getDateStr();
        }
        Page<WeComUserVo> page = new Page<>();
        page.setCurrentPage(param.getPageNum());
        Integer totalSize = weComUserMapperExt.countGroupSendUserByDate(start, end, preSendDate, param.getCarrierIds());
        page.setTotalSize(totalSize);
        if (totalSize == 0) {
            return page;
        }
        int offset = 0;
        if (Objects.nonNull(param.getPageSize())) {
            page.setPageSize(param.getPageSize());
            offset = (param.getPageNum() - 1) * param.getPageSize();
        }
        List<WeComUserBo> list = weComUserMapperExt.getGroupSendUserByDate(start, end, preSendDate, param.getCarrierIds(),
                offset, param.getPageSize());
        List<WeComUserVo> weComUserVoList = new ArrayList<>();
        for (WeComUserBo weComUserBo : list) {
            WeComUserVo weComUserVo = new WeComUserVo();
            BeanUtils.copyProperties(weComUserBo, weComUserVo);
            int strategy;
            if (Objects.equals(weComUserBo.getStrategyStatus(), PreSpecialStatusEnum.TAG.getStatus())) {
                if (weComUserBo.getSendGender() != null) {
                    strategy = 200001;
                } else if (StringUtils.isNotEmpty(weComUserBo.getContent()) && weComUserBo.getContent().contains("${name}")) {
                    strategy = 200002;
                } else {
                    strategy = 200000;
                }
            } else {
                if (weComUserBo.getSendGender() != null) {
                    strategy = 100001;
                } else if (StringUtils.isNotEmpty(weComUserBo.getContent()) && weComUserBo.getContent().contains("${name}")) {
                    strategy = 100002;
                } else {
                    strategy = 100000;
                }
            }
            weComUserVo.setStrategy(strategy);
            weComUserVoList.add(weComUserVo);
        }
        page.setObjs(weComUserVoList);
        return page;
    }


    public List<Long> getFilterTagUserId() {
        List<Long> needFilterTagIdList = JSONArray.parseArray(needFilterTagIdConfig, Long.class);
        if (CollectionUtils.isEmpty(needFilterTagIdList)) {
            return new ArrayList<>();
        }
        UserWithTagExample example = new UserWithTagExample();
        example.createCriteria().andTagIdIn(needFilterTagIdList).andIsDeleteEqualTo(0);
        List<UserWithTag> userWithTags = userWithTagMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(userWithTags)) {
            return new ArrayList<>();
        }
        return userWithTags.stream().map(UserWithTag::getUserId).distinct().collect(Collectors.toList());
    }

    public List<Long> getFilterTagId() {
        List<Long> needFilterTagIdList = JSONArray.parseArray(needFilterTagIdConfig, Long.class);
        if (CollectionUtils.isEmpty(needFilterTagIdList)) {
            return new ArrayList<>();
        }
        return needFilterTagIdList;
    }

    @Override
    public List<Staff> getStaffByUserId(Long userId) {
        StaffWithUserExample example = new StaffWithUserExample();
        example.createCriteria().andUserIdEqualTo(userId).andIsDeleteEqualTo(0);
        List<StaffWithUser> staffWithUsers = staffWithUserMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(staffWithUsers)) {
            return null;
        }
        List<Staff> allStaffs = new ArrayList<>();
        for (StaffWithUser staffWithUser : staffWithUsers) {
            StaffExample staffExample = new StaffExample();
            staffExample.createCriteria().andIdEqualTo(staffWithUser.getStaffId());
            List<Staff> staffs = staffMapper.selectByExample(staffExample);
            if (!CollectionUtils.isEmpty(staffs)) {
                allStaffs.addAll(staffs);
            }
        }
        return allStaffs;
    }

    @Override
    public CommonResponse<Void> addUserTag(UserTagParam userTagParam) {
        if (userTagParam == null
                || StringUtils.isEmpty(userTagParam.getUnionId())
                || StringUtils.isEmpty(userTagParam.getTagGroupName())
                || StringUtils.isEmpty(userTagParam.getTagName())) {
            return CommonResponse.create(500, "参数错误");
        }
        TagExample example = new TagExample();
        example.createCriteria().andTagGroupNameEqualTo(userTagParam.getTagGroupName())
                .andTagNameEqualTo(userTagParam.getTagName())
                .andIsDeleteEqualTo(0);
        List<Tag> tags = tagMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(tags)) {
            return CommonResponse.create(500, "标签不存在");
        }
        Tag tag = tags.get(0);
        WeComUserExample userExample = new WeComUserExample();
        userExample.createCriteria().andUnionIdEqualTo(userTagParam.getUnionId());
        List<WeComUser> weComUsers = weComUserMapper.selectByExample(userExample);
        if (CollectionUtils.isEmpty(weComUsers)) {
            return CommonResponse.create(500, "用户不存在");
        }
        WeComUser weComUser = weComUsers.get(0);
        UserWithTag userWithTag = new UserWithTag();
        userWithTag.setTagId(tag.getId());
        userWithTag.setUserId(weComUser.getId());
        boolean b = addUserWithTag(userWithTag);
        if (b) {
            boolean b1 = addWeComTag(tag, weComUser);
            if (!b1) {
                UserWithTag record = new UserWithTag();
                record.setStatus(2);
                UserWithTagExample userWithTagExample = new UserWithTagExample();
                userWithTagExample.createCriteria().andUserIdEqualTo(userWithTag.getUserId()).andTagIdEqualTo(userWithTag.getTagId());
                userWithTagMapper.updateByExampleSelective(record, userWithTagExample);
                LarkRobotUtil.sendMessage("企微添加标签失败 tagId=" + tag.getId() + "   userId=" + weComUser.getId());
            }
        } else {
            return CommonResponse.create(500, "添加失败");
        }
        return CommonResponse.success();
    }

    private boolean addWeComTag(Tag tag, WeComUser weComUser) {
        if (tag == null || weComUser == null) {
            return false;
        }
        try {
            String accessToken = weComAccessTokenService.getWeComAccessToken(weComUser.getCorpId());
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(tag.getTagId());
            StaffWithUserExample staffWithUserExample = new StaffWithUserExample();
            staffWithUserExample.createCriteria().andUserIdEqualTo(weComUser.getId()).andIsDeleteEqualTo(0);
            List<StaffWithUser> staffWithUsers = staffWithUserMapper.selectByExample(staffWithUserExample);
            if (!CollectionUtils.isEmpty(staffWithUsers)) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("userid", "ShengHuoLeQu");
                jsonObject.put("external_userid", weComUser.getExternalUserId());
                jsonObject.put("add_tag", jsonArray);
                String url = POST_WE_COM_ADD_USER_TAG + "?access_token=" + accessToken;
                String post = httpPoolClient.post(url, jsonObject.toJSONString());
                JSONObject jsonObject1 = JSONObject.parseObject(post);
                if (jsonObject1.getInteger("errcode") == 0) {
                    return true;
                }
            }
        } catch (Exception e) {
            log.error("addWeComTag error", e);
        }
        return false;
    }

    public boolean addUserWithTag(UserWithTag userWithTag) {
        try {
            UserWithTagExample userWithTagExample = new UserWithTagExample();
            userWithTagExample.createCriteria().andUserIdEqualTo(userWithTag.getUserId())
                    .andTagIdEqualTo(userWithTag.getTagId());
            List<UserWithTag> userWithTags = userWithTagMapper.selectByExample(userWithTagExample);
            if (CollectionUtils.isEmpty(userWithTags)) {
                userWithTagMapper.insertSelective(userWithTag);
            } else {
                UserWithTag userWithTag1 = userWithTags.get(0);
                if (userWithTag1.getIsDelete() == 1) {
                    userWithTag1.setIsDelete(0);
                    userWithTagMapper.updateByPrimaryKeySelective(userWithTag1);
                }
            }
            return true;
        } catch (Exception e) {
            log.error("addUserWithTag error", e);
        }
        return false;
    }

    public boolean delAllUserTag(Long userId) {
        try {
            UserWithTagExample userWithTagExample = new UserWithTagExample();
            userWithTagExample.createCriteria().andUserIdEqualTo(userId).andStatusEqualTo(1);
            UserWithTag record = new UserWithTag();
            record.setIsDelete(1);
            userWithTagMapper.updateByExampleSelective(record, userWithTagExample);
            return true;
        } catch (Exception e) {
            log.error("addUserWithTag error", e);
        }
        return false;
    }

    public void updateUserWithTag(Long userId, List<String> tagIdList) {
        try {
            TagExample example = new TagExample();
            example.createCriteria().andTagIdIn(tagIdList).andIsDeleteEqualTo(0);
            List<Tag> tags = tagMapper.selectByExample(example);
            List<Long> tagIds = tags.stream().map(Tag::getId).collect(Collectors.toList());
            UserWithTagExample userWithTagExample = new UserWithTagExample();
            userWithTagExample.createCriteria().andUserIdEqualTo(userId).andIsDeleteEqualTo(0);
            List<UserWithTag> userWithTags = userWithTagMapper.selectByExample(userWithTagExample);
            List<Long> userTagIds = userWithTags.stream().map(UserWithTag::getTagId).collect(Collectors.toList());
            userTagIds.removeAll(tagIds);
            if (!CollectionUtils.isEmpty(userTagIds)) {
                List<UserWithTag> collect = userWithTags.stream()
                        .filter(f -> userTagIds.contains(f.getTagId())).collect(Collectors.toList());
                for (UserWithTag userWithTag : collect) {
                    if (userWithTag.getStatus() == 2) {
                        WeComUser weComUser = weComUserMapper.selectByPrimaryKey(userWithTag.getUserId());
                        Tag tag = tagMapper.selectByPrimaryKey(userWithTag.getTagId());
                        addWeComTag(tag, weComUser);
                    } else {
                        userWithTag.setIsDelete(1);
                        userWithTagMapper.updateByPrimaryKeySelective(userWithTag);
                    }
                }
            }
            List<Long> hasUserTagIds = userWithTags.stream().map(UserWithTag::getTagId).collect(Collectors.toList());
            tagIds.removeAll(hasUserTagIds);
            if (!CollectionUtils.isEmpty(tagIds)) {
                for (Long tagId : tagIds) {
                    UserWithTag userWithTag = new UserWithTag();
                    userWithTag.setTagId(tagId);
                    userWithTag.setUserId(userId);
                    addUserWithTag(userWithTag);
                }
            }
        } catch (Exception e) {
            log.error("updateUserWithTag error", e);
        }
    }
}
