package com.nbport.zgwl.partner.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nbport.zgwl.common.PageResult;
import com.nbport.zgwl.exception.ServiceException;
import com.nbport.zgwl.partner.dto.PartnerContactDto;
import com.nbport.zgwl.partner.dto.PartnerManageDto;
import com.nbport.zgwl.partner.dto.PartnerQueryDto;
import com.nbport.zgwl.partner.handler.PartnerDataHandler;
import com.nbport.zgwl.partner.mapper.PartnerManageMapper;
import com.nbport.zgwl.partner.utils.PartnerIdUtils;
import com.nbport.zgwl.partner.utils.PartnerManageConstants;
import com.nbport.zgwl.partner.utils.PartnerSyncPayloadBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 相对方管理 Service 实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PartnerManageServiceImpl implements PartnerManageService {

    private final PartnerManageMapper partnerManageMapper;

    private final PartnerDataHandler partnerDataHandler;

    /** 分页查询相对方列表（结果中会带上联系人数据） */
    @Override
    public PageResult<PartnerManageDto> queryPartnerList(PartnerQueryDto queryDto) {
        Page<PartnerManageDto> page = new Page<>(queryDto.getPageNo(), queryDto.getPageSize());
        queryDto.setOrgId(1L);
        Page<PartnerManageDto> resultPage = (Page<PartnerManageDto>) partnerManageMapper.selectPartnerPage(page, queryDto);
        PageResult<PartnerManageDto> pageResult = new PageResult<>(resultPage);
        attachContacts(pageResult.getData());
        return pageResult;
    }

    /** 根据主键查询单个相对方详情（含联系人） */
    @Override
    public PartnerManageDto selectPartnerById(Long customerSysid) {
        PartnerManageDto partner = partnerManageMapper.selectPartnerById(customerSysid);
        if (partner == null) {
            throw new ServiceException("相对方不存在");
        }
        attachContacts(Collections.singletonList(partner));
        return partner;
    }

    /** 新增相对方（含联系人信息保存，数据回写主键） */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insertPartner(PartnerManageDto partner) {
        partnerDataHandler.normalizeBeforeSave(partner);
        partnerDataHandler.validateForSave(partner);

        LocalDateTime now = LocalDateTime.now();
        partner.setCustomerSysid(partnerManageMapper.selectPartnerSeqNextVal());
        partner.setOppositeCode(ensureOppositeCode(partner.getOppositeCode()));
        partner.setOppositeId(null);
        partner.setSyncStatus(PartnerManageConstants.SYNC_STATUS_UNSYNCED);
        partner.setSyncTime(null);
        partner.setSyncMessage("新增后尚未同步");
        partner.setOppositeStatus(PartnerManageConstants.OPPOSITE_STATUS_EFFECTUAL);
        partner.setCreateBy(PartnerManageConstants.DEFAULT_OPERATOR);
        partner.setCreateTime(now);
        partner.setUpdateBy(PartnerManageConstants.DEFAULT_OPERATOR);
        partner.setUpdateTime(now);
        partner.setOrgId(1L);
        partner.setIsDeleted(PartnerManageConstants.PARTNER_IS_DELETED_NORMAL);

        partnerManageMapper.insertPartner(partner);
        saveContacts(partner.getCustomerSysid(), partner.getContacts(), now);
        return partner.getCustomerSysid();
    }

    /** 修改相对方（先删旧联系人，再批量插入新联系人） */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePartner(PartnerManageDto partner) {
        if (partner.getCustomerSysid() == null) {
            throw new ServiceException("修改时 customerSysid 不能为空");
        }

        PartnerManageDto dbPartner = partnerManageMapper.selectPartnerById(partner.getCustomerSysid());
        if (dbPartner == null) {
            throw new ServiceException("相对方不存在或已删除");
        }

        partnerDataHandler.normalizeBeforeSave(partner);
        partnerDataHandler.validateForSave(partner);

        LocalDateTime now = LocalDateTime.now();
        partner.setOppositeCode(ensureOppositeCode(partner.getOppositeCode(), dbPartner.getOppositeCode()));
        partner.setOppositeId(dbPartner.getOppositeId());
        partner.setOppositeStatus(ensureValue(partner.getOppositeStatus(), dbPartner.getOppositeStatus(),
                PartnerManageConstants.OPPOSITE_STATUS_EFFECTUAL));
        partner.setSyncStatus(PartnerManageConstants.SYNC_STATUS_UNSYNCED);
        partner.setSyncTime(null);
        partner.setSyncMessage("信息已修改，待重新同步");
        partner.setUpdateBy(PartnerManageConstants.DEFAULT_OPERATOR);
        partner.setUpdateTime(now);
        partner.setOrgId(1L);
        partner.setIsDeleted(PartnerManageConstants.PARTNER_IS_DELETED_NORMAL);
        partnerManageMapper.updatePartner(partner);
        partnerManageMapper.markPartnerContactsDeletedByPartnerId(
                partner.getCustomerSysid(),
                PartnerManageConstants.DEFAULT_OPERATOR,
                now,
                PartnerManageConstants.CONTACT_DEL_FLAG_DELETED);
        saveContacts(partner.getCustomerSysid(), partner.getContacts(), now);
    }

    /** 批量删除相对方（逻辑删除，同时删除关联联系人） */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePartnerByIds(List<Long> customerSysids) {
        if (customerSysids == null || customerSysids.isEmpty()) {
            return;
        }
        LocalDateTime now = LocalDateTime.now();
        partnerManageMapper.markPartnerContactsDeletedByPartnerIds(
                customerSysids,
                PartnerManageConstants.DEFAULT_OPERATOR,
                now,
                PartnerManageConstants.CONTACT_DEL_FLAG_DELETED);
        partnerManageMapper.deletePartnerByIds(
                customerSysids,
                PartnerManageConstants.DEFAULT_OPERATOR,
                now,
                PartnerManageConstants.PARTNER_IS_DELETED_DELETED);
    }

    /** 模拟同步相对方到法务系统（本地测试用，TODO：替换为真实 collectOpposites 调用） */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PartnerManageDto mockSyncPartner(Long customerSysid) {
        PartnerManageDto partner = partnerManageMapper.selectPartnerById(customerSysid);
        if (partner == null) {
            throw new ServiceException("相对方不存在或已删除");
        }

        attachContacts(Collections.singletonList(partner));

        LocalDateTime now = LocalDateTime.now();
        String oppositeId = StrUtilHelper.hasText(partner.getOppositeId())
                ? partner.getOppositeId()
                : PartnerIdUtils.buildGroupPartnerId();

        PartnerSyncPayloadBuilder.buildCollectOppositesPayload(partner);
        // PushPayloadDTO payloadDTO =
        // PartnerSyncPayloadBuilder.buildCollectOppositesPayload(partner);
        // Map<String, Object> response =
        // dataCollectionPushService.collectOpposites(payloadDTO);
        String syncMessage = "本地测试模拟同步成功。TODO：后续在这里调用相对方信息采集接口 collectOpposites。";
        // // 从法务系统响应中取出返回的 oppositeId（比如 response 里有个 "jtId" 字段）
        // String oppositeIdFromLawSystem = ...; // 具体 key 看法务返回的字段名
        // String syncMessage = response.containsKey("msg")
        // ? String.valueOf(response.get("msg"))
        // : "相对方信息采集同步成功";

        // // 回写法务返回的 oppositeId，而不是本地生成的
        partnerManageMapper.updatePartnerSyncInfo(
                customerSysid,
                oppositeId,
                PartnerManageConstants.SYNC_STATUS_SYNCED,
                now,
                syncMessage,
                PartnerManageConstants.DEFAULT_OPERATOR,
                now);
        return selectPartnerById(customerSysid);
    }

    /** 批量查询并填充联系人（避免 N+1，一次查完再分组赋值） */
    private void attachContacts(List<PartnerManageDto> partnerList) {
        if (partnerList == null || partnerList.isEmpty()) {
            return;
        }

        List<Long> customerSysids = partnerList.stream()
                .map(PartnerManageDto::getCustomerSysid)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (customerSysids.isEmpty()) {
            return;
        }

        List<PartnerContactDto> contacts = partnerManageMapper.selectPartnerContactsByPartnerIds(customerSysids);
        Map<Long, List<PartnerContactDto>> contactMap = contacts.stream()
                .collect(Collectors.groupingBy(PartnerContactDto::getPartnerRecordId));

        partnerList.forEach(item -> {
            List<PartnerContactDto> currentContacts = contactMap.getOrDefault(item.getCustomerSysid(),
                    Collections.emptyList());
            partnerDataHandler.fillContactUiKeys(currentContacts);
            item.setContacts(currentContacts);
        });
    }

    /** 批量保存联系人（设置排序号、删除标记后统一插入） */
    private void saveContacts(Long customerSysid, List<PartnerContactDto> contacts, LocalDateTime now) {
        if (customerSysid == null || contacts == null || contacts.isEmpty()) {
            return;
        }

        int sortOrder = 1;
        for (PartnerContactDto contact : contacts) {
            contact.setId(partnerManageMapper.selectPartnerContactSeqNextVal());
            contact.setPartnerRecordId(customerSysid);
            contact.setSortOrder(sortOrder++);
            contact.setDelFlag(PartnerManageConstants.CONTACT_DEL_FLAG_NORMAL);
        }

        partnerManageMapper.batchInsertPartnerContacts(
                contacts,
                PartnerManageConstants.DEFAULT_OPERATOR,
                now,
                PartnerManageConstants.DEFAULT_OPERATOR,
                now,
                PartnerManageConstants.CONTACT_DEL_FLAG_NORMAL);
    }

    private String ensureOppositeCode(String oppositeCode) {
        return ensureOppositeCode(oppositeCode, null);
    }

    private String ensureOppositeCode(String oppositeCode, String fallback) {
        if (StrUtilHelper.hasText(oppositeCode)) {
            return oppositeCode;
        }
        if (StrUtilHelper.hasText(fallback)) {
            return fallback;
        }
        return PartnerIdUtils.buildPartnerId();
    }

    private String ensureValue(String value, String fallback, String defaultValue) {
        if (StrUtilHelper.hasText(value)) {
            return value;
        }
        if (StrUtilHelper.hasText(fallback)) {
            return fallback;
        }
        return defaultValue;
    }

    /**
     * 避免为了一个判空再引入新依赖，这里保留一个最小工具。
     */
    private static final class StrUtilHelper {

        private StrUtilHelper() {
        }

        private static boolean hasText(String value) {
            return value != null && !value.isBlank();
        }
    }
}
