package com.cloudcc.core;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;

import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.ClasspathHelper;
import org.apache.log4j.BasicConfigurator;

public class TriggerInvoker {
    UserInfo uinfo = null;
    String operate = "";
    String triggerTime = "";

    public TriggerInvoker(UserInfo userInfo, String operate, String triggerTime) {
        this.uinfo = userInfo;
        this.operate = operate;
        this.triggerTime = triggerTime;
    }

    public TriggerInvoker() {

    }

    @SuppressWarnings("rawtypes")
    public ServiceResult handler(CCObject data) throws Exception {
        String objectApiName = data.getObjectApiName();
        ServiceResult sr = new ServiceResult();
        // 初始化 log4j，避免无 appender 的警告
        try {
            BasicConfigurator.configure();
        } catch (Exception ignore) {
        }
        // 使用包名前缀的简便构造，这会启用默认的扫描器（包含 SubTypesScanner）
        Reflections ref = new Reflections("com.cloudcc.trigger");
        Set<Class<? extends CCTrigger>> clsSets = null;
        try {
            clsSets = ref.getSubTypesOf(CCTrigger.class);
        } catch (org.reflections.ReflectionsException rex) {
            // 没有配置 SubTypesScanner 或未找到任何触发器时，使用空集合继续执行
            clsSets = java.util.Collections.emptySet();
        }
        for (Class<? extends CCTrigger> subCls : clsSets) {
            try {
                Constructor cons = subCls.getConstructor(CCObject.class, CCObject.class, ServiceResult.class,
                        UserInfo.class);
                CCTrigger trigger = (CCTrigger) cons.newInstance(data, null, sr, uinfo);
                String objectApiNameTmp = (String) trigger.getObjectApiName();
                if (objectApiName != null && objectApiName.equals(objectApiNameTmp)) {
                    if ("before".equals(triggerTime) && "insert".equals(operate)) {
                        trigger.do_insert_before();
                    }
                    if ("after".equals(triggerTime) && "insert".equals(operate)) {
                        String id = (String) data.get("id");
                        trigger.setRecordOldVal(id);
                        trigger.do_insert_after();
                    }
                    if ("before".equals(triggerTime) && "update".equals(operate)) {
                        trigger.do_update_before();
                    }
                    if ("after".equals(triggerTime) && "update".equals(operate)) {
                        String id = (String) data.get("id");
                        trigger.setRecordOldVal(id);
                        trigger.do_update_after();
                    }
                    if ("before".equals(triggerTime) && "upsert".equals(operate)) {
                        trigger.do_upsert_before();
                    }
                    if ("after".equals(triggerTime) && "upsert".equals(operate)) {
                        String id = (String) data.get("id");
                        trigger.setRecordOldVal(id);
                        trigger.do_upsert_after();
                    }
                    if ("before".equals(triggerTime) && "delete".equals(operate)) {
                        trigger.do_delete_before();
                    }
                    if ("after".equals(triggerTime) && "delete".equals(operate)) {
                        String id = (String) data.get("id");
                        trigger.setRecordOldVal(id);
                        trigger.do_delete_after();
                    }
                    if ("approval".equals(operate)) {
                        trigger.do_approval();
                    }
                }
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (Exception ex) {
                throw ex;
            }
        }
        return sr;
    }
}
