package com.fs.company.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.common.annotation.DataScope;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCacheT;
import com.fs.common.utils.DateUtils;
import com.fs.company.domain.*;
import com.fs.company.mapper.*;
import com.fs.company.service.*;
import com.fs.company.service.impl.call.node.AiAddWxTaskNode;
import com.fs.enums.ExecutionStatusEnum;
import com.fs.enums.NodeTypeEnum;
import com.fs.wxcid.domain.CidIpadServerUser;
import com.fs.wxcid.domain.WxContact;
import com.fs.wxcid.dto.friend.ContactItem;
import com.fs.wxcid.dto.friend.ContactListResponse;
import com.fs.wxcid.dto.friend.GetContactDetailsListParam;
import com.fs.wxcid.dto.friend.GetContactDetailsResponseData;
import com.fs.wxcid.dto.friend.GetContactListParam;
import com.fs.wxcid.dto.login.AccountIdParam;
import com.fs.wxcid.dto.login.GetLoginQrCodeParam;
import com.fs.wxcid.dto.login.LoginStatusResponseData;
import com.fs.wxcid.dto.message.ChatroomMember;
import com.fs.wxcid.dto.message.UserNameWrapper;
import com.fs.wxcid.dto.user.UserInfo;
import com.fs.wxcid.dto.user.UserInfoExt;
import com.fs.wxcid.dto.user.UserProfileData;
import com.fs.wxcid.mapper.wx.ModContactDbMapper;
import com.fs.wxcid.service.*;
import com.fs.wxcid.service.impl.LoginServiceImpl;
import com.fs.wxcid.service.impl.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 企微账号Service业务层处理
 *
 * @author fs
 * @date 2024-12-09
 */
@Slf4j
@Service
public class CompanyWxServiceImpl extends ServiceImpl<CompanyWxAccountMapper, CompanyWxAccount> implements ICompanyWxAccountService {
    private final static String FRIEND_KEY = "cid:wx:friend-list:";
    private final static List<String> REMOVE_FRIEND_STR_ARRAY = Arrays.asList("weixin", "fmessage", "medianote", "gh_3dfda90e39d6", "qqmail");
    private final static String IS_ROOM_KEY = "@chatroom";



    private static final long SYNC_INTERVAL = 30 * 1000; // 同步间隔时间
    private static final int BATCH_SIZE = 100; // 批量插入批次大小

    @Autowired
    private CompanyWxAccountMapper companyWxAccountMapper;
    @Autowired
    private CompanyWxClientMapper companyWxClientMapper;
    @Autowired
    private LoginServiceImpl loginService;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private ICidIpadServerService cidIpadServerService;
    @Autowired
    private ICidIpadServerUserService cidIpadServerUserService;
    @Autowired
    private AdminLicenseService adminLicenseService;
    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private FriendService friendService;
    @Autowired
    private MessageCallbackService messageCallbackService;
    @Autowired
    private RedisCacheT<List<String>> friendListRedis;
    @Autowired
    private ModContactDbMapper modContactDbMapper;
    @Autowired
    private IWxContactService wxContactService;
    @Autowired
    private IWxRoomService wxRoomService;
    @Autowired
    private IWxRoomMembersService wxRoomMembersService;
    @Autowired
    private CompanyAiWorkflowExecMapper companyAiWorkflowExecMapper;
    @Autowired
    private CompanyWorkflowEngine companyWorkflowEngine;
    @Autowired
    private CompanyAiWorkflowExecLogMapper companyAiWorkflowExecLogMapper;

    @Autowired
    CompanyAiWorkflowServerMapper companyAiWorkflowServerMapper;


    /**
     * 查询企微账号
     *
     * @param id 企微账号ID
     * @return 企微账号
     */
    @Override
    public CompanyWxAccount selectCompanyWxAccountById(Long id)
    {
        return companyWxAccountMapper.selectCompanyWxAccountById(id);
    }

    /**
     * 查询企微账号列表
     *
     * @param companyWxAccount 企微账号
     * @return 企微账号
     */
    @Override
    public List<CompanyWxAccount> selectCompanyWxAccountList(CompanyWxAccount companyWxAccount)
    {
        return companyWxAccountMapper.selectCompanyWxAccountList(companyWxAccount);
    }
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<CompanyWxAccount> selectCompanyWxAccountListCompany(CompanyWxAccount companyWxAccount)
    {
        return companyWxAccountMapper.selectCompanyWxAccountListCompany(companyWxAccount);
    }

    /**
     * 新增企微账号
     *
     * @param companyWxAccount 企微账号
     * @return 结果
     */
    @Override
    public int insertCompanyWxAccount(CompanyWxAccount companyWxAccount)
    {
        companyWxAccount.setCreateTime(DateUtils.getNowDate());
        return companyWxAccountMapper.insertCompanyWxAccount(companyWxAccount);
    }

    /**
     * 修改企微账号
     *
     * @param companyWxAccount 企微账号
     * @return 结果
     */
    @Override
    public int updateCompanyWxAccount(CompanyWxAccount companyWxAccount)
    {
        return companyWxAccountMapper.updateCompanyWxAccount(companyWxAccount);
    }

    /**
     * 批量删除企微账号
     *
     * @param ids 需要删除的企微账号ID
     * @return 结果
     */
    @Override
    public int deleteCompanyWxAccountByIds(Long[] ids)
    {
        return companyWxAccountMapper.deleteCompanyWxAccountByIds(ids);
    }

    /**
     * 删除企微账号信息
     *
     * @param id 企微账号ID
     * @return 结果
     */
    @Override
    public int deleteCompanyWxAccountById(Long id)
    {
        return companyWxAccountMapper.deleteCompanyWxAccountById(id);
    }

    @Override
    public List<CompanyUser> companyListAll() {
        return companyWxAccountMapper.companyListAll();
    }

    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<CompanyUser> companyListAllCompany(CompanyUser companyUser) {
        return companyWxAccountMapper.companyListAllCompany(companyUser);
    }

    @Override
    public CompanyWxAccount selectByCompanyUserAndWxNo(Long userId, String wxNo) {
        return companyWxAccountMapper.selectByCompanyUserAndWxNo(userId, wxNo);
    }

    @Override
    public String getWxQrCode(Long accountId, String ipadOrMac) {
        CompanyWxAccount account = getById(accountId);
        if(account.getAuthKey() == null){
            String token = adminLicenseService.getToken(accountId);
            account.setAuthKey(token);
            updateById(account);
        }
        GetLoginQrCodeParam param = new GetLoginQrCodeParam();
        param.setAccountId(accountId);
        param.setIpadOrMac(ipadOrMac);
        return loginService.getLoginQrCodeNewDirect(param);
    }

    @Override
    public boolean getLoginStatus(Long accountId) {
        CompanyWxAccount account = getById(accountId);
        try {
            AccountIdParam param = new AccountIdParam();
            param.setAccountId(accountId);
            LoginStatusResponseData login = loginService.checkLoginStatus(param);
            if(login.getRet() == 0){
                account.setLoginStatus(1);
                account.setLoginTime(LocalDateTime.now());
                updateById(account);
                return true;
            }else{
                return false;
            }
        }catch (Exception e){
            return false;
        }
    }

    @Override
    public R bindService(Long accountId) {
        CompanyWxAccount account = getById(accountId);
        Company company = companyService.selectCompanyById(account.getCompanyId());
        if(company !=null && company.getMaxPadNum() != null && company.getMaxPadNum() != -1){
            int padCount = baseMapper.selectCount(new QueryWrapper<CompanyWxAccount>()
                    .eq("company_id", company.getCompanyId())
                    .isNotNull("server_id"));
            if (padCount>=company.getMaxPadNum()){
                return R.error(501,"该销售公司绑定pad数量超过限制");
            }
        }
        Integer serverStatus = account.getServerStatus();
        if (serverStatus!=null && serverStatus==1){
            return R.error("已经绑定过");
        }
        CompanyUser companyUser = companyUserService.selectCompanyUserById(account.getCompanyUserId());
        if (companyUser==null){
            return R.error("未绑定销售");
        }
        String addressId = companyUser.getAddressId();
        if (addressId==null || addressId.isEmpty()){
            return R.error("请先绑定地址");
        }
        Long cidServerId = companyUser.getCidServerId();
        if ( cidServerId==null ){
            return R.error("请先绑定cid服务");
        }
        CompanyAiWorkflowServer cidServer = companyAiWorkflowServerMapper.selectCompanyAiWorkflowServerById(companyUser.getCidServerId());

        Long serverId = cidIpadServerService.selectQwIpadServerByAddressId(addressId,cidServer.getGroupNo());
        if (serverId==null){
            return  R.error(501,"该地区服务器剩余数量不足");
        }
        account.setServerId(serverId);
        account.setServerStatus(1);
        updateById(account);

//        cidIpadServerService.subtractServer(serverId);
        CidIpadServerUser qwIpadServerUser = new CidIpadServerUser();
        qwIpadServerUser.setCompanyUserId(companyUser.getUserId());
        qwIpadServerUser.setCompanyId(companyUser.getCompanyId());
        qwIpadServerUser.setCreateTime(new Date());
        qwIpadServerUser.setServerId(serverId);
        qwIpadServerUser.setQwUserId(account.getId());
        cidIpadServerUserService.save(qwIpadServerUser);
        return null;
    }

    @Override
    public void wakeUpLogin(Long accountId) {
        AccountIdParam param = new AccountIdParam();
        param.setAccountId(accountId);
        loginService.wakeUpLogin(param);
    }

    @Override
    public void updateWxInfo(Long accountId) {
        CompanyWxAccount account = getById(accountId);
        AccountIdParam param = new AccountIdParam();
        param.setAccountId(accountId);
        UserProfileData profile = userService.getProfile(param);
        UserInfo userInfo = profile.getUserInfo();
        UserInfoExt userInfoExt = profile.getUserInfoExt();
        account.setWxNickName(userInfo.getNickName().getStr());
        account.setWxNo(userInfo.getUserName().getStr());
        account.setHeadImgUrl(userInfoExt.getBigHeadImgUrl());
        account.setPhone(userInfo.getBindMobile().getStr());
        updateById(account);
    }

    @Override
    public void wxLoginOut(Long accountId) {
        CompanyWxAccount account = getById(accountId);
        account.setLoginStatus(0);
        account.setOutTime(LocalDateTime.now());
        account.setOutRemark("手动退出");
        updateById(account);
        AccountIdParam param = new AccountIdParam();
        param.setAccountId(accountId);
        loginService.logOut(param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncWx(Long accountId) {
        // 1. 参数校验
        if (accountId == null) {
            log.error("同步微信信息失败：accountId不能为空");
            throw new IllegalArgumentException("accountId不能为空");
        }

        // 2. 获取账号信息并更新同步时间
        CompanyWxAccount account = getById(accountId);
        if (account == null) {
            log.error("同步微信信息失败：个微账号不存在，accountId={}", accountId);
            throw new RuntimeException("个微账号不存在，accountId=" + accountId);
        }
        account.setSyncFriendTime(LocalDateTime.now());

        try {
            // 3. 清理Redis缓存
            String key = FRIEND_KEY + accountId;
            friendListRedis.deleteObject(key);

            // 4. 获取好友列表并过滤
            GetContactListParam param = new GetContactListParam();
            param.setAccountId(accountId);
            ContactListResponse response = friendService.getContactListNotKey(param);
            List<String> friendList = getFilteredFriendList(response);
            if (CollectionUtils.isEmpty(friendList)) {
                log.info("账号暂无需要同步的微信好友/群聊，accountId={}", accountId);
                updateById(account);
                return;
            }

            // 5. 缓存好友列表到Redis
            friendListRedis.setCacheObject(key, friendList);

            // 6. 同步联系人信息
            syncContactDetails(accountId, account, friendList);

            // 7. 更新账号信息
            updateById(account);

            log.info("微信信息同步完成，accountId={}，同步联系人数量={}", accountId, friendList.size());
        } catch (Exception e) {
            log.error("同步微信信息异常，accountId={}", accountId, e);
            throw e;
        }
    }

    /**
     * 获取过滤后的好友列表
     */
    private List<String> getFilteredFriendList(ContactListResponse response) {
        if (response == null || response.getContactList() == null ||
                CollectionUtils.isEmpty(response.getContactList().getContactUsernameList())) {
            return Collections.emptyList();
        }
        // 过滤掉无效的好友标识
        return response.getContactList().getContactUsernameList()
                .stream().filter(e -> !REMOVE_FRIEND_STR_ARRAY.contains(e)).collect(Collectors.toList());
    }

    /**
     * 同步联系人详情信息
     */
    private void syncContactDetails(Long accountId, CompanyWxAccount account, List<String> friendList) {
        List<WxContact> wxContacts = new ArrayList<>();
        List<WxRoom> wxRooms = new ArrayList<>();
        List<WxRoomMembers> wxRoomMembersList = new ArrayList<>();

        for (String username : friendList) {
            try {
                // 获取联系人详情
                GetContactDetailsListParam param = new GetContactDetailsListParam();
                param.setAccountId(accountId);
                param.setWxIdList(Collections.singletonList(username));
                GetContactDetailsResponseData contactDetails = friendService.getContactDetailsList(param);
                if (contactDetails == null || CollectionUtils.isEmpty(contactDetails.getContactList())) {
                    log.warn("联系人详情为空，username={}，accountId={}", username, accountId);
                    continue;
                }

                // 根据类型处理不同的联系人
                List<ContactItem> contactList = contactDetails.getContactList();
                if (username.endsWith("@chatroom")) {
                    // 处理群聊信息
                    convertToWxRoom(contactList, wxRooms);
                    // 处理群成员信息
                    convertToWxRoomMembers(contactList, wxRoomMembersList);
                } else {
                    // 处理个人好友信息
                    convertToWxContact(contactList, accountId, account, wxContacts);
                }

                // 控制同步频率，避免接口限流
                Thread.sleep(SYNC_INTERVAL);
            } catch (InterruptedException e) {
                log.error("同步联系人信息被中断，username={}，accountId={}", username, accountId, e);
                Thread.currentThread().interrupt(); // 恢复中断状态
                break; // 中断循环，避免无效执行
            } catch (Exception e) {
                log.error("同步单个联系人信息失败，username={}，accountId={}", username, accountId, e);
                // 继续处理下一个联系人，不中断整体同步
                continue;
            }
        }
        // 批量插入数据（设置批次大小，避免一次性插入过多数据）
        batchSaveData(wxContacts, wxRooms, wxRoomMembersList);
    }

    /**
     * 批量保存数据
     */
    private void batchSaveData(List<WxContact> wxContacts, List<WxRoom> wxRooms, List<WxRoomMembers> wxRoomMembersList) {
        // 保存群聊信息
        if (!CollectionUtils.isEmpty(wxRooms)) {
            wxRoomService.saveBatch(wxRooms, BATCH_SIZE);
        }
        // 保存个人好友信息
        if (!CollectionUtils.isEmpty(wxContacts)) {
            wxContactService.saveBatch(wxContacts, BATCH_SIZE);
        }
        // 保存群成员信息
        if (!CollectionUtils.isEmpty(wxRoomMembersList)) {
            wxRoomMembersService.saveBatch(wxRoomMembersList, BATCH_SIZE);
        }
    }

    /**
     * 转换为WxRoom对象
     */
    private void convertToWxRoom(List<ContactItem> contactList, List<WxRoom> wxRooms) {
        ContactItem contactItem = contactList.get(0);
        if (contactItem == null) {
            return;
        }
        WxRoom wxRoom = new WxRoom();
        wxRoom.setRoomId(getStringValue(contactItem.getUserName()));
        wxRoom.setRoomName(getStringValue(contactItem.getNickName()));
        wxRoom.setRoomOwnerId(contactItem.getChatRoomOwner());
        wxRoom.setChatroomMaxCount(parseInt(contactItem.getChatroomMaxCount()));
        wxRoom.setMemberCount(parseInt(contactItem.getNewChatroomData() != null ? contactItem.getNewChatroomData().getMemberCount() : null));
        wxRoom.setCreateTime(DateUtils.getNowDate());
        wxRoom.setUpdateTime(DateUtils.getNowDate());
        wxRooms.add(wxRoom);
    }

    /**
     * 转换为WxRoomMembers对象
     */
    private void convertToWxRoomMembers(List<ContactItem> contactList, List<WxRoomMembers> wxRoomMembersList) {
        ContactItem contactItem = contactList.get(0);
        if (contactItem == null || contactItem.getNewChatroomData() == null ||
                CollectionUtils.isEmpty(contactItem.getNewChatroomData().getChatroomMemberList())) {
            return;
        }

        String roomId = getStringValue(contactItem.getUserName());
        String roomName = getStringValue(contactItem.getNickName());
        String roomOwnerId = contactItem.getChatRoomOwner();

        for (ChatroomMember chatroomMember : contactItem.getNewChatroomData().getChatroomMemberList()) {
            if (chatroomMember == null) {
                continue;
            }
            WxRoomMembers wxRoomMembers = new WxRoomMembers();
            wxRoomMembers.setRoomId(roomId);
            wxRoomMembers.setRoomName(roomName);
            wxRoomMembers.setRoomOwnerId(roomOwnerId);
            wxRoomMembers.setRoomMemberId(chatroomMember.getUserName());
            wxRoomMembers.setRoomMemberName(chatroomMember.getNickName());
            wxRoomMembers.setChatroomMemberFlag(chatroomMember.getChatroomMemberFlag());
            wxRoomMembers.setCreateTime(DateUtils.getNowDate());
            wxRoomMembers.setUpdateTime(DateUtils.getNowDate());
            wxRoomMembersList.add(wxRoomMembers);
        }
    }

    /**
     * 转换为WxContact对象
     */
    private void convertToWxContact(List<ContactItem> contactList, Long accountId,
                                    CompanyWxAccount account, List<WxContact> wxContacts) {
        ContactItem contactItem = contactList.get(0);
        if (contactItem == null) {
            return;
        }
        WxContact wxContact = new WxContact();
        wxContact.setUserName(getStringValue(contactItem.getUserName()));
        wxContact.setNickName(getStringValue(contactItem.getNickName()));
        wxContact.setQuanPin(getStringValue(contactItem.getQuanPin()));
        wxContact.setSex(contactItem.getSex());
        wxContact.setAlias(contactItem.getAlias());
        wxContact.setHeadImgUrl(contactItem.getBigHeadImgUrl());
        wxContact.setEncryptUserName(contactItem.getEncryptUserName());
        wxContact.setProvince(contactItem.getProvince());
        wxContact.setCity(contactItem.getCity());
        wxContact.setAccountId(accountId);
        wxContact.setCompanyId(account.getCompanyId());
        wxContact.setCompanyUserId(account.getCompanyUserId());
        wxContact.setCreateTime(DateUtils.getNowDate());
        wxContact.setUpdateTime(DateUtils.getNowDate());
        wxContacts.add(wxContact);
    }

    /**
     * 安全获取字符串值（避免空指针）
     */
    private String getStringValue(UserNameWrapper obj) {
        return obj != null && obj.getStr() != null ? obj.getStr() : "";
    }

    /**
     * 安全转换为整数
     */
    private Integer parseInt(Object value) {
        if (value == null) {
            return 0;
        }
        try {
            return Integer.valueOf(value.toString());
        } catch (NumberFormatException e) {
            log.warn("转换整数失败，value={}", value);
            return 0;
        }
    }


    @Override
    public void isCheckContact(String formUser, Long accountId) {
        GetContactDetailsListParam param = new GetContactDetailsListParam();
        param.setAccountId(accountId);
        param.setWxIdList(Collections.singletonList(formUser));
        GetContactDetailsResponseData details = friendService.getContactDetailsList(param);
        details.getContactList().forEach(e -> {
            String v3 = e.getEncryptUserName();
//            String v4 = null;
//            Optional<VerifyUserValidTicketListVo> optional = details.getVerifyUserValidTicketList().stream().filter(v -> formUser.equals(v.getUsername())).findAny();
//            if(optional.isPresent()){
//                v4 = optional.get().getAntispamticket();
//            }
            CompanyWxClient companyWxClient = companyWxClientMapper.selectWx(accountId, v3);
            companyWxClient.setIsAdd(1);
            companyWxClient.setWxNo(e.getAlias());
            companyWxClient.setWxName(e.getNickName().getStr());
            companyWxClient.setAvatar(e.getBigHeadImgUrl());
            companyWxClient.setSuccessAddTime(LocalDateTime.now());
            companyWxClientMapper.updateById(companyWxClient);
            wxContactService.add(companyWxClient.getCustomerId(), companyWxClient.getPhone(), accountId, e);

            // 加微成功后，触发工作流继续执行
            triggerWorkflowOnAddWxSuccess(companyWxClient.getId());
        });
    }

    public void mockInterface(Long wxClientId){
        triggerWorkflowOnAddWxSuccess(wxClientId);
    }
    /**
     * 加微成功后触发工作流继续执行
     * @param wxClientId 加微客户ID
     */
    private void triggerWorkflowOnAddWxSuccess(Long wxClientId) {
        try {
            // 查找等待中的加微工作流实例
            CompanyAiWorkflowExec waitingExec = companyAiWorkflowExecMapper.selectWaitingAddWxWorkflowByWxClientId(
                    wxClientId,
                    ExecutionStatusEnum.WAITING.getValue(),
                    NodeTypeEnum.AI_ADD_WX_TASK.getValue());
            //查询工作流加微执行日志是否未更新状态
            CompanyAiWorkflowExecLog queryP = new CompanyAiWorkflowExecLog();
            queryP.setWorkflowInstanceId(waitingExec.getWorkflowInstanceId());
            queryP.setNodeType(NodeTypeEnum.AI_ADD_WX_TASK.getValue());
            queryP.setStatus(ExecutionStatusEnum.WAITING.getValue());
            List<CompanyAiWorkflowExecLog> companyAiWorkflowExecLogs = companyAiWorkflowExecLogMapper.selectCompanyAiWorkflowExecLogList(queryP);
            companyAiWorkflowExecLogs.forEach(log -> {
                log.setStatus(ExecutionStatusEnum.SUCCESS.getValue());
                companyAiWorkflowExecLogMapper.updateById(log);
                }
            );
            if (waitingExec == null) {
                log.info("未找到等待中的加微工作流实例 - wxClientId: {}", wxClientId);
                return;
            }

            String workflowInstanceId = waitingExec.getWorkflowInstanceId();
            String currentNodeKey = waitingExec.getCurrentNodeKey();

            log.info("加微成功回调，尝试触发工作流继续执行 - workflowInstanceId: {}, nodeKey: {}, wxClientId: {}",
                    workflowInstanceId, currentNodeKey, wxClientId);

            // 互斥检查：如果已经被执行过（超时路径或其他回调），则不再执行
            if (!AiAddWxTaskNode.tryMarkAsExecuted(workflowInstanceId, wxClientId)) {
                log.info("工作流已被其他路径执行，跳过 - workflowInstanceId: {}, wxClientId: {}",
                        workflowInstanceId, wxClientId);
                return;
            }

            // 清除超时检测Key（回调成功了，不需要超时检测了）
//            AiAddWxTaskNode.clearTimeoutKey(workflowInstanceId, wxClientId);

            // 触发工作流继续执行
            Map<String, Object> inputData = new HashMap<>();
            inputData.put("addWxSuccess", true);
            inputData.put("wxClientId", wxClientId);
            inputData.put("triggerType", "callback"); // 回调触发

            companyWorkflowEngine.resumeFromBlockingNode(workflowInstanceId, currentNodeKey, inputData);

            log.info("加微成功回调触发工作流继续执行完成 - workflowInstanceId: {}, wxClientId: {}",
                    workflowInstanceId, wxClientId);

        } catch (Exception ex) {
            log.error("加微成功回调触发工作流异常 - wxClientId: {}", wxClientId, ex);
        }
    }
}
