package com.nbport.zgwl.partner.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
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.utils.PartnerManageConstants;
import org.springframework.stereotype.Component;

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

/**
 * 相对方数据处理器
 *
 * 核心逻辑：相对方有 4 种性质（境内组织/境内个人/境外组织/境外个人），
 * 不同性质需要填写的字段完全不同。这里集中处理字段清洗、校验和默认值填充，
 * 避免 Service 层代码臃肿。
 */
@Component
public class PartnerDataHandler {

    /**
     * 保存前数据清洗。
     *
     * 根据相对方性质分类，把不需要的字段置空。比如境内组织不需要填 TIN 号，
     * 境外组织不需要填统一社会信用代码。最后给缺失的字段补上默认值。
     *
     * oppositeCharacter 对照：
     *   "1" = 境内组织, "2" = 境内个人, "3" = 境外组织, "4" = 境外个人
     */
    public void normalizeBeforeSave(PartnerManageDto partner) {
        // ========== 所有字段去前后空格 ==========
        partner.setCustomerNameC(StrUtil.trim(partner.getCustomerNameC()));
        partner.setCustomerTaxno(StrUtil.trim(partner.getCustomerTaxno()));
        partner.setCustomerRegaddr(StrUtil.trim(partner.getCustomerRegaddr()));
        partner.setEmailAddress(StrUtil.trim(partner.getEmailAddress()));
        partner.setCountry(StrUtil.trim(partner.getCountry()));
        partner.setCountryName(StrUtil.trim(partner.getCountryName()));
        partner.setLegalPersonName(StrUtil.trim(partner.getLegalPersonName()));
        partner.setCertificateNum(StrUtil.trim(partner.getCertificateNum()));
        partner.setTinCode(StrUtil.trim(partner.getTinCode()));
        partner.setRegCapital(StrUtil.trim(partner.getRegCapital()));
        partner.setOppositeCode(StrUtil.trim(partner.getOppositeCode()));
        partner.setOppositeStatus(StrUtil.trim(partner.getOppositeStatus()));
        partner.setComments(StrUtil.trim(partner.getComments()));
        partner.setRemark(StrUtil.trim(partner.getRemark()));
        partner.setSyncMessage(StrUtil.trim(partner.getSyncMessage()));

        // ========== 按相对方性质，清空不相关的字段 ==========

        // 组织性质不是"企业"（QY）时，企业二级分类没有意义，直接清掉
        if (!"QY".equals(partner.getNatureOfEnterpriseOrg())) {
            partner.setNatureOfEnterpriseOrgLev(null);
        }

        // 只有境内组织才需要统一社会信用代码和法定代表人，其他性质清空
        if (!isDomesticOrg(partner)) {
            partner.setCustomerTaxno(null);
            partner.setLegalPersonName(null);
        }

        // 只有个人（境内或境外）才需要证件类型和证件号，组织类清空
        if (!isDomesticPerson(partner) && !isForeignPerson(partner)) {
            partner.setCertificateType(null);
            partner.setCertificateNum(null);
        }

        // 只有境外组织才需要 TIN 号（税务识别号）
        if (!isForeignOrg(partner)) {
            partner.setTinCode(null);
        }

        // 非境外（组织或个人都不属于）时，国家和国家名称不需要
        if (!isForeignOrg(partner) && !isForeignPerson(partner)) {
            partner.setCountry(null);
            partner.setCountryName(null);
        }

        // 个人类型（境内/境外）不需要注册地址和注册资本
        if (!isDomesticOrg(partner) && !isForeignOrg(partner)) {
            partner.setCustomerRegaddr(null);
            partner.setRegCapital(null);
            partner.setRegisteredCapital(null);
        }

        // 只有境内组织/个人才显示涉港澳台选项，境外不涉及
        if (!showGatFlag(partner)) {
            partner.setGatFlag(PartnerManageConstants.GAT_FLAG_NO);
        }

        // ========== 字段默认值填充（前端没传就用默认值） ==========

        // 是否集团内，默认 "N"（否）
        partner.setGroupFlag(StrUtil.blankToDefault(partner.getGroupFlag(), PartnerManageConstants.GROUP_FLAG_NO));
        // 是否涉港澳台，默认 "N"（否）
        partner.setGatFlag(StrUtil.blankToDefault(partner.getGatFlag(), PartnerManageConstants.GAT_FLAG_NO));
        // 同步状态，默认 "unsynced"（未同步）
        partner.setSyncStatus(StrUtil.blankToDefault(partner.getSyncStatus(), PartnerManageConstants.SYNC_STATUS_UNSYNCED));
        // 相对方状态，默认 "EFFECTUAL"（有效）
        partner.setOppositeStatus(StrUtil.blankToDefault(partner.getOppositeStatus(), PartnerManageConstants.OPPOSITE_STATUS_EFFECTUAL));
        // 删除标记，默认 "N"（未删除）
        partner.setIsDeleted(StrUtil.blankToDefault(partner.getIsDeleted(), PartnerManageConstants.PARTNER_IS_DELETED_NORMAL));

        // isSgat 和 isJtn 由 gatFlag / groupFlag 自动推导（法务系统需要的冗余字段）
        partner.setIsSgat(PartnerManageConstants.GAT_FLAG_YES.equals(partner.getGatFlag())
                ? PartnerManageConstants.FLAG_ONE
                : PartnerManageConstants.FLAG_ZERO);
        partner.setIsJtn(PartnerManageConstants.GROUP_FLAG_YES.equals(partner.getGroupFlag())
                ? PartnerManageConstants.FLAG_ONE
                : PartnerManageConstants.FLAG_ZERO);

        // ========== 清洗联系人数据 ==========
        List<PartnerContactDto> contacts = partner.getContacts() == null ? new ArrayList<>() : partner.getContacts();
        contacts = contacts.stream()
                .filter(Objects::nonNull)               // 去掉空对象
                .peek(this::normalizeContact)            // 逐个清洗（去空格、设默认值）
                .filter(this::hasAnyContactValue)        // 去掉全空的联系人
                .collect(Collectors.toList());
        partner.setContacts(contacts);
    }

    /**
     * 保存前数据校验。
     *
     * 根据相对方不同性质，校验对应的必填字段。规则与 normalizeBeforeSave 对应：
     *   - 境内组织：必填 统一社会信用代码、法定代表人、注册地址、注册资本
     *   - 境内个人：必填 证件类型、证件号码
     *   - 境外组织：必填 TIN号、国家、注册地址、注册资本
     *   - 境外个人：必填 国家
     *   - 组织类型（境内/境外组织）：必填 联系人和邮箱
     *
     * 所有性质通用必填：公司名称、公司类型、公司性质、组织性质、是否集团内
     */
    public void validateForSave(PartnerManageDto partner) {
        // ========== 通用必填校验 ==========
        if (StrUtil.isBlank(partner.getCustomerNameC())) {
            throw new ServiceException("公司名称不能为空");
        }
        if (StrUtil.isBlank(partner.getRelativeType())) {
            throw new ServiceException("公司类型不能为空");
        }
        if (StrUtil.isBlank(partner.getOppositeCharacter())) {
            throw new ServiceException("公司性质不能为空");
        }
        if (StrUtil.isBlank(partner.getNatureOfEnterpriseOrg())) {
            throw new ServiceException("组织性质不能为空");
        }
        // 如果组织性质选了"企业"，必须选企业二级分类（如国企/民企/外企）
        if ("QY".equals(partner.getNatureOfEnterpriseOrg()) && StrUtil.isBlank(partner.getNatureOfEnterpriseOrgLev())) {
            throw new ServiceException("组织性质选择企业时，组织性质企业二级不能为空");
        }
        if (StrUtil.isBlank(partner.getGroupFlag())) {
            throw new ServiceException("是否集团内不能为空");
        }

        // ========== 按性质校验专属必填字段 ==========
        if (isDomesticOrg(partner) && StrUtil.isBlank(partner.getCustomerTaxno())) {
            throw new ServiceException("境内组织必须填写统一社会信用代码");
        }
        if (isDomesticPerson(partner) && StrUtil.isBlank(partner.getCertificateType())) {
            throw new ServiceException("境内个人必须选择自然人证件类型");
        }
        if (isDomesticPerson(partner) && StrUtil.isBlank(partner.getCertificateNum())) {
            throw new ServiceException("境内个人必须填写自然人证件号码");
        }
        if (isForeignOrg(partner) && StrUtil.isBlank(partner.getTinCode())) {
            throw new ServiceException("境外组织必须填写TIN号");
        }
        if (isForeignOrg(partner) && StrUtil.isBlank(partner.getCountry())) {
            throw new ServiceException("境外组织必须选择国家");
        }
        if (isForeignPerson(partner) && StrUtil.isBlank(partner.getCountry())) {
            throw new ServiceException("境外个人必须选择国家");
        }
        if (isDomesticOrg(partner) && StrUtil.isBlank(partner.getLegalPersonName())) {
            throw new ServiceException("境内组织必须填写法定代表人或负责人");
        }
        // 组织类型（不论境内境外）都需要注册地址和注册资本
        if ((isDomesticOrg(partner) || isForeignOrg(partner)) && StrUtil.isBlank(partner.getCustomerRegaddr())) {
            throw new ServiceException("组织类型必须填写注册地址");
        }
        if ((isDomesticOrg(partner) || isForeignOrg(partner)) && StrUtil.isBlank(partner.getRegCapital())) {
            throw new ServiceException("组织类型必须填写注册资本");
        }

        // ========== 校验联系人 ==========
        validateContacts(partner);
    }

    /** 给联系人填充前端 uid（用于列表渲染时的临时唯一标识） */
    public void fillContactUiKeys(List<PartnerContactDto> contacts) {
        if (contacts == null) {
            return;
        }
        contacts.forEach(contact -> {
            if (StrUtil.isBlank(contact.getUid())) {
                contact.setUid(contact.getId() == null ? null : String.valueOf(contact.getId()));
            }
        });
    }

    /** 校验联系人信息（姓名/电话/地址/邮箱必填，邮箱格式校验） */
    private void validateContacts(PartnerManageDto partner) {
        if (!needContacts(partner)) {
            return;
        }
        if (CollUtil.isEmpty(partner.getContacts())) {
            throw new ServiceException("组织类型至少需要维护一个联系人");
        }
        for (PartnerContactDto contact : partner.getContacts()) {
            if (StrUtil.isBlank(contact.getContactName())) {
                throw new ServiceException("联系人姓名不能为空");
            }
            if (StrUtil.isBlank(contact.getContactPhone())) {
                throw new ServiceException("联系人联系电话不能为空");
            }
            if (StrUtil.isBlank(contact.getPostalAddress())) {
                throw new ServiceException("联系人通讯地址不能为空");
            }
            if (StrUtil.isBlank(contact.getEmail())) {
                throw new ServiceException("联系人电子邮箱不能为空");
            }
            if (!Validator.isEmail(contact.getEmail())) {
                throw new ServiceException("联系人电子邮箱格式不正确");
            }
        }
    }

    /** 清洗单条联系人数据（去空格、设置默认删除标记） */
    private void normalizeContact(PartnerContactDto contact) {
        contact.setContactName(StrUtil.trim(contact.getContactName()));
        contact.setContactPhone(StrUtil.trim(contact.getContactPhone()));
        contact.setPostalAddress(StrUtil.trim(contact.getPostalAddress()));
        contact.setEmail(StrUtil.trim(contact.getEmail()));
        contact.setRemark(StrUtil.trim(contact.getRemark()));
        contact.setDelFlag(PartnerManageConstants.CONTACT_DEL_FLAG_NORMAL);
    }

    /** 判断联系人是否有有效数据（至少填写一个字段才保留） */
    private boolean hasAnyContactValue(PartnerContactDto contact) {
        return StrUtil.isNotBlank(contact.getContactName())
                || StrUtil.isNotBlank(contact.getContactPhone())
                || StrUtil.isNotBlank(contact.getPostalAddress())
                || StrUtil.isNotBlank(contact.getEmail());
    }

    /** 是否需要维护联系人（境内组织、境外组织必须维护） */
    private boolean needContacts(PartnerManageDto partner) {
        return isDomesticOrg(partner) || isForeignOrg(partner);
    }

    /** 是否显示涉港澳台标识（境内组织、境内个人才显示） */
    private boolean showGatFlag(PartnerManageDto partner) {
        return isDomesticOrg(partner) || isDomesticPerson(partner);
    }

    /**
     * 相对方是否属于境内组织。
     * oppositeCharacter = "1" 时表示境内组织。
     */
    private boolean isDomesticOrg(PartnerManageDto partner) {
        return "1".equals(partner.getOppositeCharacter());
    }

    /**
     * 相对方是否属于境内个人。
     * oppositeCharacter = "2" 时表示境内个人。
     */
    private boolean isDomesticPerson(PartnerManageDto partner) {
        return "2".equals(partner.getOppositeCharacter());
    }

    /**
     * 相对方是否属于境外组织。
     * oppositeCharacter = "3" 时表示境外组织。
     */
    private boolean isForeignOrg(PartnerManageDto partner) {
        return "3".equals(partner.getOppositeCharacter());
    }

    /**
     * 相对方是否属于境外个人。
     * oppositeCharacter = "4" 时表示境外个人。
     */
    private boolean isForeignPerson(PartnerManageDto partner) {
        return "4".equals(partner.getOppositeCharacter());
    }
}
