package com.kingdee.eas.custom.integration.feishu.app;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.IObjectPK;
import com.kingdee.bos.dao.IObjectValue;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.bos.metadata.entity.FilterInfo;
import com.kingdee.bos.metadata.entity.FilterItemCollection;
import com.kingdee.bos.metadata.entity.FilterItemInfo;
import com.kingdee.bos.metadata.entity.SelectorItemCollection;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.eas.base.permission.UserInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.integration.feishu.*;
import com.kingdee.eas.custom.integration.feishu.bizEnum.LocaleEnum;
import com.kingdee.eas.custom.integration.feishu.bizEnum.SyncStatusEnum;
import com.kingdee.eas.custom.integration.feishu.bizEnum.ViewerTypeEnum;
import com.kingdee.shr.base.syssetting.BaseItemException;
import com.kingdee.shr.base.syssetting.util.BaseMetaDataUtil;
import com.lark.oapi.Client;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.approval.v4.model.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.text.MessageFormat;
import java.util.*;

/**
 * 飞书审批定义
 */
public class FeishuApprovalsControllerBean extends AbstractFeishuApprovalsControllerBean {
    private static Logger logger = Logger.getLogger(FeishuApprovalsControllerBean.class);
    //业务系统名称
    private final String BIZ_NAME = "金蝶_sHR";

    @Override
    protected IObjectPK _save(Context ctx, IObjectValue model) throws BOSException, EASBizException {
        FeishuApprovalsInfo info = (FeishuApprovalsInfo) model;
        //审批定义code
        String number = info.getNumber();
        if (StringUtils.isBlank(number)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"审批定义code不能为空！"});
        }

        //模型
        String entityName = info.getModel();
        if (StringUtils.isBlank(entityName)) {
            throw new BOSException("单据模型不能为空!");
        }

        FilterInfo filterInfo = new FilterInfo();
        FilterItemCollection filterItems = filterInfo.getFilterItems();
        filterItems.add(new FilterItemInfo("model", entityName));
        if (info.getId() != null) {
            filterItems.add(new FilterItemInfo("id", info.getId(), CompareType.NOTEQUALS));
        }
        if (exists(ctx, filterInfo)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"单据模型[" + entityName + "]已存在！"});
        }
        //审批名称
        FeishuI18nResourcesInfo approvalName = info.getApprovalName();

        if (approvalName == null) {
            throw new BOSException("审批名称不能为空!");
        }
        if (!"default".equals(entityName)) {
            //是否不存在
            boolean entityNonExists = BaseMetaDataUtil.isEntityNonExists(ctx, entityName);
            if (entityNonExists) {
                throw new BOSException("单据模型[" + entityName + "]未找到，请检查模型路径是否有误！");
            }
        }

        String name = approvalName.getName();
        if (StringUtils.isBlank(name)) {
            IFeishuI18nResources iFeishuI18nResources = FeishuI18nResourcesFactory.getLocalInstance(ctx);
            approvalName = iFeishuI18nResources.getFeishuI18nResourcesInfo(new ObjectUuidPK(approvalName.getId()));
            name = approvalName.getName();
        }
        info.setName(name);
        IObjectPK iObjectPK = super._save(ctx, model);
        //同步飞书审批定义
        syncFeishuApprovals(ctx, iObjectPK.toString());
        return iObjectPK;
    }


    /**
     * 新增
     *
     * @param ctx
     * @param model
     * @return
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected IObjectPK _addnew(Context ctx, IObjectValue model) throws BOSException, EASBizException {
        FeishuApprovalsInfo feishuApprovalsInfo = (FeishuApprovalsInfo) model;
        //重置状态
        feishuApprovalsInfo.setSyncStatus(SyncStatusEnum.UNSYNC);
        IObjectPK iObjectPK = super._addnew(ctx, model);
        //启用
        _enable(ctx, iObjectPK.toString());
        return iObjectPK;


    }

    @Override
    protected void _update(Context ctx, IObjectPK pk, IObjectValue model) throws BOSException, EASBizException {
        FeishuApprovalsInfo feishuApprovalsInfo = (FeishuApprovalsInfo) model;
        //重置状态
        feishuApprovalsInfo.setSyncStatus(SyncStatusEnum.UNSYNC);
        super._update(ctx, pk, model);
    }

    /**
     * 同步飞书审批定义
     *
     * @param ctx
     * @param billID
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _syncFeishuApprovals(Context ctx, String billID) throws BOSException, EASBizException {
        logger.info("同步飞书审批定义开始, billID: " + billID);
        super._syncFeishuApprovals(ctx, billID);
        SelectorItemCollection sic = new SelectorItemCollection();
        sic.add("*");
        sic.add("approvalName.*");
        sic.add("approvalName.entrys.*");
        sic.add("group.number");
        sic.add("group.groupName.*");
        sic.add("group.groupName.entrys.*");
        sic.add("views.viewerType");
        sic.add("views.viewerUser.number");
        sic.add("views.viewerUser.feishuUserId");
        sic.add("managers.managerUser.number");
        sic.add("managers.managerUser.feishuUserId");

        //审批定义
        FeishuApprovalsInfo feishuApprovalsInfo = getFeishuApprovalsInfo(ctx, new ObjectUuidPK(billID), sic);
        //审批定义code
        String number = feishuApprovalsInfo.getNumber();
        if (StringUtils.isBlank(number)) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"审批定义code为空！"});
        }
        SelectorItemCollection updateSic = new SelectorItemCollection();
        updateSic.add("approvalCode");
        updateSic.add("syncStatus");
        updateSic.add("syncResult");
        try {
            //请求创建审批定义
            CreateExternalApprovalResp result = createExternalApproval(ctx, feishuApprovalsInfo);
            logger.info("同步审批定义请求结果: " + Jsons.DEFAULT.toJson(result.getData()));
            // 处理服务端错误
            if (result.success()) {
                CreateExternalApprovalRespBody data = result.getData();
                // 业务数据处理
                logger.info("创建审批定义请求成功: " + Jsons.DEFAULT.toJson(data));
                //审批定义code
                feishuApprovalsInfo.setApprovalCode(data.getApprovalCode());

                feishuApprovalsInfo.setSyncStatus(SyncStatusEnum.SUCCESS);
                feishuApprovalsInfo.setSyncResult("同步成功!");
            } else {
                //请求失败
                feishuApprovalsInfo.setSyncStatus(SyncStatusEnum.FAIL);
                String msgFormat = "错误码: {0}\n报错信息: {1}\n完整错误信息: {2}";
                feishuApprovalsInfo.setSyncResult(MessageFormat.format(msgFormat, result.getCode(), result.getMsg(), result.getError()));
            }
            //更新
            updatePartial(ctx, feishuApprovalsInfo, updateSic);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BOSException(e);
        }
    }

    /**
     * 请求创建审批定义
     *
     * @param ctx
     * @param feishuApprovalsInfo
     * @return
     * @throws Exception
     */
    private CreateExternalApprovalResp createExternalApproval(Context ctx, FeishuApprovalsInfo feishuApprovalsInfo)
            throws Exception {
        //获取默认配置
        IFeishuConfig iFeishuConfig = FeishuConfigFactory.getLocalInstance(ctx);
        FeishuConfigCollection defaultConfigs = iFeishuConfig.getDefaultConfigs();
        if (defaultConfigs.isEmpty()) {
            throw new BaseItemException(BaseItemException.CUSTOM_EXCEPTION, new Object[]{"未匹配到默认飞书应用配置！"});
        }
        FeishuConfigInfo feishuConfigInfo = defaultConfigs.get(0);
        // 构建client
        Client client = Client.newBuilder(feishuConfigInfo.getAppID(), feishuConfigInfo.getAppSecret()).build();
        // 分组
        FeishuApprovalGroupInfo group = feishuApprovalsInfo.getGroup();
        //审批定义名称
        FeishuI18nResourcesInfo approvalNameResources = feishuApprovalsInfo.getApprovalName();
        // 分组名称资源
        FeishuI18nResourcesInfo groupNameResources = group.getGroupName();
        //获取国际化资源
        I18nResource[] i18nResources = getI18nResources(approvalNameResources, groupNameResources);
        //获取三方审批相关信息
        ApprovalCreateExternal external = getApprovalCreateExternal(feishuApprovalsInfo);
        //获取审批可见人列表
        ApprovalCreateViewers[] tenants = getApprovalCreateViewers(feishuApprovalsInfo);
        //获取管理员列表
        String[] managers = getManagers(feishuApprovalsInfo);
        // 创建请求对象
        CreateExternalApprovalReq req = CreateExternalApprovalReq.newBuilder()
                .userIdType("open_id")//用户 ID 类型，默认值：open_id，user_id
                .externalApproval(ExternalApproval.newBuilder()
                        .approvalName(approvalNameResources.getNumber())//审批定义名称
                        .approvalCode(feishuApprovalsInfo.getNumber())//审批定义编码
                        .groupCode(group.getNumber())//分组编码
                        .groupName(groupNameResources.getNumber())//分组名称
                        .external(external)//三方审批相关信息
                        .viewers(tenants)//审批可见人列表,可见人类型，生效优先级NONE>TENANT>指定范围
                        .i18nResources(i18nResources)//审批定义名称资源
                        .managers(managers)//管理员
                        .build())
                .build();
        // 发起请求
        return client.approval().v4().externalApproval().create(req);
    }

    /**
     * 获取国际化资源
     *
     * @param resources 多语言资源
     * @return
     */
    private I18nResource[] getI18nResources(FeishuI18nResourcesInfo... resources) {
//        Set<LocaleEnum> localeSet = new HashSet<LocaleEnum>();
//        Map<LocaleEnum, I18nResourceText> i18nResourceTextMap = new HashMap<>();
        List<I18nResourceText> i18nResourceTexts = new ArrayList();

        for (FeishuI18nResourcesInfo resource : resources) {
            if (resource != null) {
                Map<LocaleEnum, I18nResourceText> resourcesMap = new HashMap<LocaleEnum, I18nResourceText>();

                FeishuI18nResourcesEntryCollection resourcesEntrys = resource.getEntrys();
                for (int i = 0; i < resourcesEntrys.size(); i++) {
                    FeishuI18nResourcesEntryInfo entryInfo = resourcesEntrys.get(i);
                    //语言
                    LocaleEnum locale = entryInfo.getLocale();
                    //localeSet.add(locale);
                    //文本
                    String value = entryInfo.getValue();
                    resourcesMap.put(locale, I18nResourceText.newBuilder()
                            .key(resource.getNumber())
                            .value(value)
                            .build());
                }
                if (resourcesMap.get(LocaleEnum.ZHCN) != null) {
                    i18nResourceTexts.add(resourcesMap.get(LocaleEnum.ZHCN));
                }
            }
        }

        I18nResourceText[] i18nResourceTextArray = i18nResourceTexts.toArray(new I18nResourceText[i18nResourceTexts.size()]);
        //国际化资源
        I18nResource[] i18nResources = {
                I18nResource.newBuilder()
                        .locale(LocaleEnum.ZHCN_VALUE)//中文
                        .texts(i18nResourceTextArray).isDefault(true)
                        .build()
        };
        return i18nResources;
    }

    /**
     * 获取管理员列表
     *
     * @param feishuApprovalsInfo
     * @return
     * @throws BOSException
     */
    private String[] getManagers(FeishuApprovalsInfo feishuApprovalsInfo) throws BOSException, EASBizException {
        //管理员
        FeishuApprovalsManagerCollection managersCollection = feishuApprovalsInfo.getManagers();

        Set<String> managerIds = new HashSet<String>();
        if (!managersCollection.isEmpty()) {
            for (int i = 0; i < managersCollection.size(); i++) {
                FeishuApprovalsManagerInfo managerInfo = managersCollection.get(i);

                UserInfo managerUser = managerInfo.getManagerUser();
                String feishuUserId = managerUser.getString("feishuUserId");
                if (StringUtils.isBlank(feishuUserId)) {
                    logger.error("用户[" + managerUser.getNumber() + "]的飞书userId为空!");
                    throw new BOSException("用户[" + managerUser.getNumber() + "]的飞书userId为空!");
                }
                managerIds.add(feishuUserId);
            }
        }

        String[] managers = managerIds.toArray(new String[managerIds.size()]);
        return managers;
    }

    /**
     * 获取三方审批相关信息
     *
     * @param feishuApprovalsInfo
     * @return
     */
    private ApprovalCreateExternal getApprovalCreateExternal(FeishuApprovalsInfo feishuApprovalsInfo) {
        //三方审批相关信息
        ApprovalCreateExternal external = ApprovalCreateExternal.newBuilder()
                .bizName(BIZ_NAME)//列表中用于提示审批来自哪个三方系统
                .bizType("workflow")//审批定义业务类别，自定义设置
                .createLinkMobile(feishuApprovalsInfo.getCreateLinkMobile())//移动端发起三方审批的链接
                .createLinkPc(feishuApprovalsInfo.getCreateLinkPc())//PC 端发起三方审批的链接
                .supportPc(feishuApprovalsInfo.isSupportPc())//是否支持PC端发起审批
                .supportMobile(feishuApprovalsInfo.isSupportMobile())//是否支持移动端发起审批
                .supportBatchRead(feishuApprovalsInfo.isSupportBatchRead())//是否支持批量已读
                .enableMarkReaded(feishuApprovalsInfo.isEnableMarkReaded())//是否支持标注可读
                .actionCallbackUrl(feishuApprovalsInfo.getCallbackUrl())//三方系统的操作回调 URL
                .actionCallbackToken(feishuApprovalsInfo.getCallbackToken())//三方系统的操作回调 Token
                .actionCallbackKey(feishuApprovalsInfo.getCallbackKey())//三方系统的操作回调 Key
                .build();
        return external;
    }

    /**
     * 获取审批可见人列表
     *
     * @param feishuApprovalsInfo
     * @return
     * @throws BOSException
     */
    private ApprovalCreateViewers[] getApprovalCreateViewers(FeishuApprovalsInfo feishuApprovalsInfo) throws BOSException {
        //审批可见人列表,可见人类型，生效优先级NONE>TENANT>指定范围
        FeishuApprovalsViewCollection views = feishuApprovalsInfo.getViews();
        List<ApprovalCreateViewers> tenantsList = new ArrayList<ApprovalCreateViewers>();
        for (int i = 0; i < views.size(); i++) {

            FeishuApprovalsViewInfo feishuApprovalsViewInfo = views.get(i);
            ViewerTypeEnum viewerType = feishuApprovalsViewInfo.getViewerType();

            if (ViewerTypeEnum.NONE.equals(viewerType)) {
                //任何人都不可见
                tenantsList.add(ApprovalCreateViewers.newBuilder()
                        .viewerType(ViewerTypeEnum.NONE_VALUE)
                        .build());
            } else if (ViewerTypeEnum.TENANT.equals(viewerType)) {
                //租户内可见
                tenantsList.add(ApprovalCreateViewers.newBuilder()
                        .viewerType(ViewerTypeEnum.TENANT_VALUE)
                        .build());
            } else if (ViewerTypeEnum.DEPARTMENT.equals(viewerType)) {
                //指定部门
                //todo 没有集成部门,暂不考虑该场景
                logger.error("指定部门");
            } else if (ViewerTypeEnum.USER.equals(viewerType)) {
                UserInfo viewerUser = feishuApprovalsViewInfo.getViewerUser();
                if (viewerUser == null) {
                    logger.error("审批可见人列表 用户为空!");
                    throw new BOSException("审批可见人列表 用户为空!");
                }
                String feishuUserId = viewerUser.getString("feishuUserId");
                if (StringUtils.isBlank(feishuUserId)) {
                    logger.error("用户[" + viewerUser.getNumber() + "]的飞书userId为空!");
                    throw new BOSException("用户[" + viewerUser.getNumber() + "]的飞书userId为空!");
                }
                tenantsList.add(ApprovalCreateViewers.newBuilder()
                        .viewerType(ViewerTypeEnum.USER_VALUE)
                        .viewerUserId(feishuUserId)
                        .build());
            }
        }
        //审批可见人列表,可见人类型，生效优先级NONE>TENANT>指定范围
        ApprovalCreateViewers[] tenants = tenantsList.toArray(new ApprovalCreateViewers[tenantsList.size()]);
        return tenants;
    }
}