package com.kingdee.eas.custom.integration.mdm.service;

import com.grapecity.documents.excel.D;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.BOSObjectFactory;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.bos.util.BOSObjectType;
import com.kingdee.bos.util.BOSUuid;
import com.kingdee.eas.basedata.org.CtrlUnitInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.integration.base.util.SHRApiUtils;
import com.kingdee.eas.custom.integration.mdm.dto.MdmFailDetail;
import com.kingdee.eas.custom.integration.mdm.dto.MdmRecord;
import com.kingdee.eas.custom.integration.mdm.dto.MdmSyncResponse;
import com.kingdee.eas.custom.integration.mdm.enums.MdmEntityEnum;
import com.kingdee.eas.custom.integration.mdm.exception.MdmErrorCodes;
import com.kingdee.eas.custom.integration.mdm.exception.MdmIntegrationException;
import com.kingdee.eas.framework.DataBaseCollection;
import com.kingdee.eas.framework.DataBaseInfo;
import com.kingdee.eas.framework.IDataBase;
import com.kingdee.eas.framework.ObjectBaseInfo;
import com.kingdee.shr.base.syssetting.BaseItemCustomInfo;
import com.kingdee.shr.compensation.app.tax.TaxUnitInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MDM 基础资料写入服务，以编码（number）为唯一键。
 * 通过 IDataBase 通用 API 操作任意 SHRBaseItem 实体，新增实体无需修改本类。
 * 写入策略：编码不存在则新增，存在且名称不一致则更新，名称一致则跳过。
 * 并发安全依赖数据库层 FNumber 唯一约束。
 */
public class MdmMasterDataService {

    private static final Logger logger = LoggerFactory.getLogger(MdmMasterDataService.class);
    private final String HRORGUNIT_ID = "00000000-0000-0000-0000-000000000000CCE7AED4";

    public MdmSyncResponse save(MdmEntityEnum entity, List<MdmRecord> records) {
        MdmSyncResponse response = new MdmSyncResponse();
        response.setTotalCount(records.size());
        Context ctx;
        try {
            ctx = SHRApiUtils.getContext();
        } catch (Exception e) {
            throw new MdmIntegrationException(MdmErrorCodes.SAVE_ERROR, "无法获取 BOS Context: " + e.getMessage());
        }
        try {
            IDataBase iBaseItem = getBaseItem(ctx, entity.bosType);
            Map<String, DataBaseInfo> existingMap = loadExistingMap(iBaseItem, entity);
            for (MdmRecord record : records) {
                try {
                    saveSingle(ctx, iBaseItem, entity, record, existingMap);
                    response.setSuccessCount(response.getSuccessCount() + 1);
                } catch (Exception e) {
                    logger.error("MDM写入接口报错： ",e);
                    response.setFailCount(response.getFailCount() + 1);
                    response.addFailDetail(new MdmFailDetail(record.getNumber(), e.getMessage()));
                }
            }
        } catch (BOSException e) {
            throw new MdmIntegrationException(MdmErrorCodes.SAVE_ERROR, "保存数据时出错: " + e.getMessage(), e);
        }
        return response;
    }

    private IDataBase getBaseItem(Context ctx, String bosType) throws BOSException {
        return (IDataBase) BOSObjectFactory.createBOSObject(ctx, new BOSObjectType(bosType));
    }

    private Map<String, DataBaseInfo> loadExistingMap(IDataBase iBaseItem, MdmEntityEnum entity) throws BOSException {
        Map<String, DataBaseInfo> map = new HashMap<>();
        DataBaseCollection col = iBaseItem.getDataBaseCollection();
        if (col != null) for (int i = 0; i < col.size(); i++) {
            DataBaseInfo info = col.get(i);
            map.put(info.getNumber(), info);
        }
        return map;
    }

    private void saveSingle(Context ctx, IDataBase iBaseItem, MdmEntityEnum entity, MdmRecord record, Map<String, DataBaseInfo> existingMap) throws BOSException {
        validateRecord(record);
        try {
            String number = record.getNumber().trim();
            DataBaseInfo existing = existingMap.get(number);
            if (existing != null) {
                if (applyUpdate(existing, record)) {
                    iBaseItem.update(new ObjectUuidPK(existing.getId()), existing);
                }
            } else {
                addNew(ctx, entity, number, record, existingMap);
            }
        } catch (EASBizException e) {
            throw new MdmIntegrationException(MdmErrorCodes.SAVE_ERROR, "保存数据时出错: " + e.getMessage(), e);
        }
    }

    private void addNew(Context ctx, MdmEntityEnum entity, String number, MdmRecord record, Map<String, DataBaseInfo> existingMap) throws BOSException {
        DataBaseInfo info = null;
        if (MdmEntityEnum.ACCOUNT_ENTITY.equals(entity)) {
            TaxUnitInfo taxUnitInfo = new TaxUnitInfo();
            taxUnitInfo.setNumber(number);
            info = taxUnitInfo;
        } else {
            BaseItemCustomInfo baseInfo = new BaseItemCustomInfo();
            baseInfo.setBOSType(new BOSObjectType(entity.bosType));
            baseInfo.setNumber(number);
            info = baseInfo;
        }
        //创建业务组织
        CtrlUnitInfo ctrlUnitInfo = new CtrlUnitInfo();
        ctrlUnitInfo.setId(BOSUuid.read("00000000-0000-0000-0000-000000000000CCE7AED4"));
        info.setCU(ctrlUnitInfo);
        //创建业务组织
        info.put("hrOrgUnit", HRORGUNIT_ID);
        applyUpdate(info, record);
        IDataBase iBaseItem = getBaseItem(ctx, entity.bosType);
        try {
            iBaseItem.addnew(info);
            existingMap.put(number, info);
        } catch (BOSException e) {
            DataBaseInfo existing = findByNumber(ctx, entity, number);
            if (existing != null) {
                //创建失败，数据已经存在，执行更新操作
                applyUpdate(existing, record);
                try {
                    iBaseItem.update(new ObjectUuidPK(existing.getId()), existing);
                } catch (EASBizException ex) {
                    throw new MdmIntegrationException(MdmErrorCodes.SAVE_ERROR, "保存数据时出错: " + ex.getMessage(), ex);
                }
                existingMap.put(number, existing);
            } else {
                throw e;
            }
        } catch (EASBizException e) {
            throw new MdmIntegrationException(MdmErrorCodes.SAVE_ERROR, "保存数据时出错: " + e.getMessage(), e);
        }
    }

    private DataBaseInfo findByNumber(Context ctx, MdmEntityEnum entity, String number) throws BOSException {
        IDataBase iBaseItem = getBaseItem(ctx, entity.bosType);
        DataBaseCollection col = iBaseItem.getDataBaseCollection();
        if (col != null) for (int i = 0; i < col.size(); i++) {
            DataBaseInfo info = col.get(i);
            if (number.equals(info.getNumber())) return info;
        }
        return null;
    }


    /**
     * 将 MDM 记录字段合并到基础资料对象；任一字段变化则返回 true 以触发 update。
     */
    private boolean applyUpdate(ObjectBaseInfo info, MdmRecord record) {
        boolean changed = false;
        if (info.getString("name") == null || !info.getString("name").equals(record.getName())) {
            //info.put("name", record.getName());
            info.put("name", record.getName(), null);
            changed = true;
        }
        resolveState(record.getState());
        if (info.get("state") == null || info.getInt("state") != record.getState()) {
            info.put("state", record.getState());
            changed = true;
        }
        return changed;
    }

    /**
     * 校验 MDM status 取值。约定：1=启用，2=禁用；未传时 MdmRecord 默认 1。
     */
    private void resolveState(int status) {
        if (status != 1 && status != 2) {
            throw new MdmIntegrationException(MdmErrorCodes.VALIDATION_ERROR, "状态(status)无效，仅支持 1(启用) 或 2(禁用)，当前: " + status);
        }
    }

    private void validateRecord(MdmRecord record) {
        if (StringUtils.isBlank(record.getNumber()))
            throw new MdmIntegrationException(MdmErrorCodes.VALIDATION_ERROR, "编码(number)不能为空");
        if (StringUtils.isBlank(record.getName()))
            throw new MdmIntegrationException(MdmErrorCodes.VALIDATION_ERROR, "名称(name)不能为空");
    }
}
