package cn.reghao.tnb.user.app.service;

import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.tnb.auth.api.dto.AccountAvatar;
import cn.reghao.tnb.auth.api.dto.AccountInfo;
import cn.reghao.tnb.auth.api.iface.AccountQuery;
import cn.reghao.tnb.common.auth.UserContext;
import cn.reghao.tnb.user.api.dto.ContactDetail;
import cn.reghao.tnb.user.api.dto.UserInfo;
import cn.reghao.tnb.user.app.db.mapper.UserContactMapper;
import cn.reghao.tnb.user.app.db.mapper.UserContactRecordMapper;
import cn.reghao.tnb.user.app.model.constant.ApplyStatus;
import cn.reghao.tnb.user.app.model.constant.FriendStatus;
import cn.reghao.tnb.user.app.model.dto.*;
import cn.reghao.tnb.user.app.model.po.UserContact;
import cn.reghao.tnb.user.app.model.po.UserContactRecord;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2023-11-28 11:47:47
 */
@Service
public class ContactService {
    private int pageSize = 10;
    @DubboReference(check = false, retries = 0, timeout = 10_000)
    private AccountQuery accountQuery;

    private final UserContactMapper userContactMapper;
    private final UserContactRecordMapper userContactRecordMapper;
    private final UserProfileService userProfileService;

    public ContactService(UserProfileService userProfileService, UserContactMapper userContactMapper,
                          UserContactRecordMapper userContactRecordMapper) {
        this.userProfileService = userProfileService;
        this.userContactMapper = userContactMapper;
        this.userContactRecordMapper = userContactRecordMapper;
    }

    public List<AccountAvatar> getContactList(int pageNumber) {
        long owner = UserContext.getUserId();
        List<UserContact> list = userContactMapper.findByOwner(owner);
        return list.stream()
                .map(userContact -> accountQuery.getAccountAvatar(userContact.getFriendId()))
                .collect(Collectors.toList());
    }

    public SearchContactResult searchUser(String mobile) {
        AccountInfo accountInfo = accountQuery.getByMobile(mobile);
        if (accountInfo != null) {
            long userId = accountInfo.getUserId();
            UserInfo userInfo = userProfileService.getUserInfo(userId);
            return new SearchContactResult(userInfo);
        }

        return null;
    }

    public ContactInfoResult getContactInfoResult(long friendId) {
        AccountInfo accountInfo = accountQuery.getAccountInfo(friendId);
        long userId = accountInfo.getUserId();
        UserInfo userInfo = userProfileService.getUserInfo(userId);
        ContactInfoResult contactInfoResult = new ContactInfoResult(userInfo);

        long loginUser = UserContext.getUserId();
        if (friendId == loginUser) {
            contactInfoResult.setFriendApply(ApplyStatus.acceptApply.getValue());
            contactInfoResult.setFriendStatus(FriendStatus.normal.getValue());
            return contactInfoResult;
        }

        UserContact userContact = userContactMapper.findByOwnerAndFriendId(loginUser, friendId);
        if (userContact != null) {
            contactInfoResult.setNicknameRemark(userContact.getRemarkName());
            contactInfoResult.setFriendStatus(FriendStatus.normal.getValue());
            contactInfoResult.setFriendApply(ApplyStatus.acceptApply.getValue());
        } else {
            UserContactRecord userContactRecord = userContactRecordMapper.findByUserIdAndFriendId(loginUser, friendId);
            if (userContactRecord != null) {
                contactInfoResult.setFriendStatus(userContactRecord.getFriendStatus());
                contactInfoResult.setFriendApply(userContactRecord.getApplyStatus());
            } else {
                contactInfoResult.setFriendStatus(FriendStatus.normal.getValue());
                contactInfoResult.setFriendApply(ApplyStatus.newApply.getValue());
            }
        }

        return contactInfoResult;
    }

    public Result createApply(ContactAdd contactAdd) {
        long applyUser = UserContext.getUserId();
        long appliedUser = contactAdd.getFriendId();
        if (userContactRecordMapper.findByUserIdAndFriendId(applyUser, appliedUser) != null) {
            return Result.success("已发送申请, 请等待结果");
        }

        String remark = contactAdd.getRemark();
        UserContactRecord userContactRecord = new UserContactRecord();
        userContactRecord.setApplyUser(applyUser);
        userContactRecord.setAppliedUser(appliedUser);
        userContactRecord.setApplyStatus(ApplyStatus.newApply.getValue());
        userContactRecord.setRemark(remark);
        userContactRecordMapper.save(userContactRecord);
        //eventService.sendApplyEvent(appliedUser);

        return Result.success();
    }

    public UnreadNum getApplyCount() {
        long loginUser = UserContext.getUserId();
        int total = userContactRecordMapper.countNewApply(loginUser);
        return new UnreadNum(total);
    }

    public ContactApplyList getApplyList(int pageNumber) {
        long loginUser = UserContext.getUserId();
        List<ContactApplyInfo> list = userContactRecordMapper.findByNewApply(loginUser);
        list.forEach(contactApplyInfo -> {
            long userId = contactApplyInfo.getUserId();
            ContactDetail contactDetail = getContactDetail(userId);
            contactApplyInfo.setNickname(contactDetail.getScreenName());
            contactApplyInfo.setAvatar(contactDetail.getAvatarUrl());
        });

        ContactApplyList contactApplyList = new ContactApplyList();
        contactApplyList.setRows(list);
        Paginate paginate = new Paginate();
        paginate.setPage(pageNumber);
        paginate.setSize(pageSize);
        paginate.setTotal(list.size());
        contactApplyList.setPaginate(paginate);
        return contactApplyList;
    }

    public ContactDetail getContactDetail(long userId) {
        UserInfo userInfo = userProfileService.getUserInfo(userId);
        return new ContactDetail(userInfo);
    }

    public void acceptApply(ContactAddRespond contactAddRespond) {
        long loginUser = UserContext.getUserId();
        int applyId = contactAddRespond.getApplyId();
        String nicknameRemark = contactAddRespond.getRemark();

        UserContactRecord userContactRecord = userContactRecordMapper.findByApplyId(applyId, loginUser);
        if (userContactRecord == null) {
            return;
        }

        long applyUserId = userContactRecord.getApplyUser();
        UserContact userContact = new UserContact(applyUserId, loginUser);
        userContact.setRemarkName(nicknameRemark);

        UserContact userContact1 = new UserContact(loginUser, applyUserId);
        save(applyId, loginUser, List.of(userContact, userContact1));
    }

    @Transactional(rollbackFor = Exception.class)
    public void save(int applyId, long loginUser, List<UserContact> userContacts) {
        userContactMapper.saveAll(userContacts);
        userContactRecordMapper.updateContactApply(applyId, loginUser, ApplyStatus.acceptApply.getValue());
    }

    public void declineApply(ContactAddRespond contactAddRespond) {
        long loginUser = UserContext.getUserId();
        int applyId = contactAddRespond.getApplyId();
        String remark = contactAddRespond.getRemark();
        userContactRecordMapper.updateContactApply(applyId, loginUser, ApplyStatus.declineApply.getValue());
    }

    public List<ContactInfo> getContactList(long owner) {
        List<UserContact> list = userContactMapper.findByOwner(owner);
        List<ContactInfo> contactInfos = list.stream().map(userContact -> {
            long friendId = userContact.getFriendId();
            UserInfo userInfo = userProfileService.getUserInfo(friendId);
            return new ContactInfo(userInfo, userContact);
        }).collect(Collectors.toList());
        return contactInfos;
    }

    public void updateContactRemark(ContactRemark contactRemark) {
        long friendId = contactRemark.getFriendId();
        String remarkName = contactRemark.getRemarkName();
        long owner = UserContext.getUserId();
        userContactMapper.updateContactRemark(friendId, remarkName, owner);
    }
}
