package com.sikey.wa04.business.infrastructure.adapter.dao;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.sikey.wa04.business.domain.adapter.ChildAdapter;
import com.sikey.wa04.business.domain.adapter.GroupAdapter;
import com.sikey.wa04.business.domain.adapter.GroupMemberAdapter;
import com.sikey.wa04.business.domain.entity.*;
import com.sikey.wa04.business.domain.usecase.ChildIdFactory;
import com.sikey.wa04.business.infrastructure.dto.model.ChildModel;
import com.sikey.wa04.business.infrastructure.dto.model.ContactModel;
import com.sikey.wa04.business.infrastructure.dto.request.messaging.ContactMessageRequest;
import com.sikey.wa04.business.infrastructure.repository.ChildRefRepository;
import com.sikey.wa04.business.infrastructure.repository.ChildRepository;
import com.sikey.wa04.business.infrastructure.repository.ContactRepository;
import com.sikey.wa04.business.infrastructure.repository.MessageRecvRepository;
import com.sikey.wa04.common.enums.Gender;
import com.sikey.wa04.common.enums.IdentityEnum;
import com.sikey.wa04.common.enums.UserType;
import com.sikey.wa04.common.exception.BusinessException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ChildAdapterImpl implements ChildAdapter {

    @Resource
    private ChildRepository childRepository;

    @Resource
    private ChildRefRepository childRefRepository;

    @Resource
    private ContactRepository contactRepository;

    @Resource
    private GroupAdapter groupAdapter;

    @Resource
    private GroupMemberAdapter groupMemberAdapter;

    @Resource
    private MessageRecvRepository messageRecvRepository;

    @Override
    public void create(Child child) {
        ChildModel childModel = convertToModel(new ChildModel(), child);
        childModel.setId(child.getId());
        log.info("Create Child : {}", JSONUtil.toJsonPrettyStr(childModel));
        childRepository.save(childModel);
    }

    @Override
    public void update(Child child) {
        childRepository.findById(child.getId()).ifPresent(model -> childRepository.save(convertToModel(model, child)));
    }

    @Transactional
    @Override
    public void updateChild(Child child, UserId userId, String appellation) {
        // Modify the contact appellation information
        ContactModel contactModel = contactRepository.findByChildIdAndRefId(child.getId(), userId.getId());
        if (Objects.nonNull(contactModel)) {
            contactModel.setRemarkName(appellation);
            contactRepository.save(contactModel);
        }

        List<ContactModel> contactModelList = contactRepository.findByRefId(child.getId());
        //更新所有好友中的昵称 和 发送变动通讯录消息通知推送给此小孩的所有好友
        if (CollectionUtil.isNotEmpty(contactModelList)) {
            for (ContactModel model : contactModelList) {
                if (model.getRefType().intValue() == UserType.CHILD.getValue()) {
                    log.info("[修改小孩]更新好友中的昵称：好友小孩Id：{};好友小孩身份：{}", model.getChildId(), model.getRefType());
                    //更新好友中的昵称
                    model.setRemarkName(child.getName());
                    model.setRemarkAvatar(child.getAvatar());
                    contactRepository.save(model);
                }
            }
        }

        childRepository.findById(child.getId()).ifPresent(model -> childRepository.save(convertChildToModel(model, child)));
    }

    public ChildModel convertToModel(ChildModel childModel, Child child) {
        return childModel.
                setChildName(child.getName()).
                setPhoneNumber(child.getPhoneNumber().number()).
                setAreaCode(child.getPhoneNumber().areaCode()).
                setAvatar(child.getAvatar()).
                setGender(child.getGender().getValue()).
                setIsEnableBlockUnknownCall(child.getIsEnableBlockUnknownCall()).
                setWeight(child.getWeight()).
                setBirthday(child.getBirthday()).
                setHeight(child.getHeight()).
                setIsEnableFence(child.getIsEnableFence());
    }

    public ChildModel convertChildToModel(ChildModel childModel, Child child) {
        return childModel.setChildName(child.getName()).setPhoneNumber(child.getPhoneNumber().number()).setAreaCode(child.getPhoneNumber().areaCode()).setAvatar(child.getAvatar()).setGender(child.getGender().getValue()).setHeight(child.getHeight()).setWeight(child.getWeight()).setBirthday(child.getBirthday());
    }

    /**
     * 删除小孩
     * @param childId  小孩ID
     * @param userId   用户ID
     * @param identity 身份：0 默认1其他人2家人3管理员4超级管理员
     */
    @Transactional
    @Override
    public void delete(ChildId childId, UserId userId, Integer identity) {
        String childIdValue = childId.getId();
        if (Objects.nonNull(identity) && (identity.intValue() == IdentityEnum.IDENTITY_ADMIN.getValue() || identity.intValue() == IdentityEnum.IDENTITY_SUPER_ADMIN.getValue())) {
            // 管理员业务
            childRepository.deleteById(childIdValue);
            // 通讯录
            contactRepository.deleteByChildId(childIdValue);
            // 删除小孩的所有手表好友的通讯录中的自己。
            contactRepository.deleteByRefId(childIdValue);
            // 用户儿童
            childRefRepository.deleteByChildId(childIdValue);
            // 群组
            Group group = groupAdapter.findByChildId(ChildIdFactory.create(childIdValue));
            // 群组
            groupAdapter.deleteByChildId(childIdValue);
            // 群组成员
            groupMemberAdapter.deleteByGroupId(group.getId().getId());
        } else {
            // 非管理员业务
            String userIdId = userId.getId();
            // 通讯录
            contactRepository.deleteByChildIdAndRefId(childIdValue, userIdId);
            // 用户儿童
            childRefRepository.deleteByChildIdAndUserId(childIdValue, userIdId);
            // 群组
            Group group = groupAdapter.findByChildId(ChildIdFactory.create(childIdValue));
            // 群组成员
            groupMemberAdapter.leave(group.getId(), new UserId(userIdId));
            // 删除私聊消息
            messageRecvRepository.deleteByRecvIdAndSendId(userIdId, childIdValue);
            // 删除群聊消息
            messageRecvRepository.deleteByRecvIdAndGroupId(userIdId, group.getId().getId());
        }
    }

    @Override
    public Child queryChild(ChildId id) {
        Optional<ChildModel> childModel = childRepository.findById(id.getId());
        childModel.orElseThrow(() -> new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "不存在该儿童"));

        ChildModel childModel1 = childModel.get();
        Child child = new Child();
        child.setId(childModel1.getId());
        child.setGender(Gender.valueOf(childModel1.getGender()));
        child.setAvatar(childModel1.getAvatar());
        child.setHeight(childModel1.getHeight());
        child.setBirthday(childModel1.getBirthday());
        child.setAreaCode(childModel1.getAreaCode());
        child.setName(childModel1.getChildName());
        return child;
    }

    /**
     * 查询儿童
     *
     * @param childRefIdList 儿童编码
     * @return
     */
    @Override
    public List<Child> findByChildIdIn(List<String> childRefIdList) {
        List<ChildModel> childModelList = childRepository.findAllById(childRefIdList);
        if (CollectionUtil.isNotEmpty(childModelList)) {
            return childModelList.stream().map(
                    childModel -> {
                        Child child = new Child();
                        child.setId(childModel.getId())
                                .setName(childModel.getChildName())
                                .setAvatar(childModel.getAvatar())
                                .setGender(Gender.valueOf(childModel.getGender()))
                                .setHeight(childModel.getHeight())
                                .setBirthday(childModel.getBirthday())
                                .setAreaCode(childModel.getAreaCode())
                                .setIsEnableBlockUnknownCall(childModel.getIsEnableBlockUnknownCall())
                                .setIsEnableFence(childModel.getIsEnableFence())
                                .setPhoneNumber(new PhoneNumber(childModel.getPhoneNumber(), childModel.getAreaCode()));
                        return child;
                    }
            ).collect(Collectors.toList());
        }
        return Collections.EMPTY_LIST;
    }
}
