package cn.ibizlab.codegen.model;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import net.ibizsys.model.dataentity.service.IPSDEMethodDTO;
import net.ibizsys.model.dataentity.service.IPSDEServiceAPI;
import net.ibizsys.model.dataentity.service.IPSDEServiceAPIMethod;
import net.ibizsys.model.dataentity.service.IPSDEServiceAPIRS;
import org.apache.commons.collections.CollectionUtils;

import java.util.*;

@Getter
@Setter
@NoArgsConstructor
@Accessors(chain = true)
public class ApiEntityModel extends BaseModel {

    private List<ApiDtoModel> dtos = new ArrayList<>();

    public ApiEntityModel(ApiModel apiModel, IPSDEServiceAPI apiDataEntity) {
        this.opt = apiDataEntity;
        this.api = apiModel;
        this.setCodeName(apiDataEntity.getCodeName());
        this.setName(apiDataEntity.getName());
        this.setId(String.format("%1$s-%2$s", api.getCodeName(), apiDataEntity.getCodeName()));
        if (apiDataEntity.getPSDataEntity() != null && apiDataEntity.getPSDataEntity().getAllPSDEMethodDTOs() != null) {
            for (IPSDEMethodDTO iPSDEMethodDTO : apiDataEntity.getPSDataEntity().getAllPSDEMethodDTOs()) {
                dtos.add(new ApiDtoModel(this, iPSDEMethodDTO));
            }
        }

    }

    public IPSDEServiceAPI getApiDataEntity() {
        return (IPSDEServiceAPI) opt;
    }

    private ApiModel api;

    public EntityModel getEntity() {
        return api.getSystem().getEntity(getApiDataEntity().getPSDataEntity().getCodeName());
    }

    private List<FieldModel> properties;

    public List<FieldModel> getProperties() {
        if (properties == null) {
            properties = new ArrayList<>();
            getEntity().getFields().forEach(field -> {
                properties.add(field);
            });
        }
        return properties;
    }


    public boolean isMajor() {
        return getApiDataEntity().isMajor();
    }


    public List<ApiMethodModel> getMethods() {
        if (this.getCodeName().equals("District")) {
            getApiDataEntity().isMajor();
        }
        List<ApiMethodModel> methods = new ArrayList<>();
        //主接口方法
        if (getApiDataEntity().isMajor() && getApiDataEntity().getPSDEServiceAPIMethods() != null) {
            for (IPSDEServiceAPIMethod iPSDEServiceAPIMethod : getApiDataEntity().getPSDEServiceAPIMethods()) {
                if(iPSDEServiceAPIMethod.getPSDEDataSet()!=null && iPSDEServiceAPIMethod.getPSDEDataSet().getPSDEDataQueries()==null)
                    continue ;
                methods.add(new ApiMethodModel(this, null, iPSDEServiceAPIMethod));
            }
        }
        //接口关系方法
        if (getApiDataEntity().getMinorPSDEServiceAPIRSs() != null) {
            for (IPSDEServiceAPIRS iPSDEServiceAPIRS : getApiDataEntity().getMinorPSDEServiceAPIRSs()) {
                if (iPSDEServiceAPIRS.getPSDEServiceAPIMethods() != null) {
                    ApiEntityRSModel apiEntityRSModel = api.getApiEntityRS(iPSDEServiceAPIRS.getName());
                    //计算父路径
                    List<List<ApiEntityRSModel>> parentApiEntityList = new ArrayList<>();
                    fillDEAPIRSPath(parentApiEntityList, apiEntityRSModel, null);
                    for (List<ApiEntityRSModel> parentApiEntities : parentApiEntityList) {
                        for (IPSDEServiceAPIMethod iPSDEServiceAPIMethod : iPSDEServiceAPIRS.getPSDEServiceAPIMethods()) {
                            if(iPSDEServiceAPIMethod.getPSDEDataSet()!=null && iPSDEServiceAPIMethod.getPSDEDataSet().getPSDEDataQueries()==null)
                                continue ;
                            methods.add(new ApiMethodModel(this, parentApiEntities, iPSDEServiceAPIMethod));
                        }
                    }
                }
            }
        }
        return methods;
    }

    /**
     * 递归计算接口关系path
     * 注意自身关系
     *
     * @param parentApiEntityList
     * @param apiEntityRSModel
     * @param parentApiEntities
     */
    private void fillDEAPIRSPath(List<List<ApiEntityRSModel>> parentApiEntityList, ApiEntityRSModel apiEntityRSModel, List<ApiEntityRSModel> parentApiEntities) {
        if (parentApiEntities == null) {
            parentApiEntities = new ArrayList<>();
        }
        //防止递归
        if (parentApiEntities.stream().anyMatch(rs -> rs.getName().equals(apiEntityRSModel.getName()))) {
            return;
        }
        parentApiEntities.add(apiEntityRSModel);
        if (apiEntityRSModel.isMajorEntityMajor()) {
            List<ApiEntityRSModel> temp = new ArrayList<>();
            temp.addAll(parentApiEntities);
            parentApiEntityList.add(temp);
        }
        //递归
        List<ApiEntityRSModel> parents = api.getApiEntityParentRSes(apiEntityRSModel.getMajorEntityCodeName());
        if (!CollectionUtils.isEmpty(parents)) {
            for (ApiEntityRSModel parentRs : parents) {
                List<ApiEntityRSModel> tempParentApiEntities = new ArrayList<>();
                tempParentApiEntities.addAll(parentApiEntities);
                fillDEAPIRSPath(parentApiEntityList, parentRs, tempParentApiEntities);
            }
        }
    }


}
