package cn.ibizlab.core.lite.extensions.service;

import cn.ibizlab.core.lite.domain.DstSystem;
import cn.ibizlab.core.lite.domain.MetaEntity;
import cn.ibizlab.core.lite.domain.MetaRelationship;
import cn.ibizlab.core.lite.extensions.domain.EntityModel;
import cn.ibizlab.core.lite.extensions.domain.FieldModel;
import cn.ibizlab.core.lite.extensions.domain.RelationshipModel;
import cn.ibizlab.core.lite.extensions.util.LiteStorage;
import cn.ibizlab.core.lite.service.*;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.sql.Wrapper;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
public class LiteModelService {

    @PostConstruct
    public void init(){
        LiteStorage.setLiteModelService(this);
    }

    @Autowired
    private IMetaEntityService metaEntityService;

    public IMetaEntityService getMetaEntityService()
    {
        return metaEntityService;
    }

    @Autowired
    private IMetaFieldService metaFieldService;

    @Autowired
    private IMetaRelationshipService metaRelationshipService;

    @Autowired
    private IDstSystemService dstSystemService;

    @Autowired
    private IDstDataSourceService dstDataSourceService;

    @Autowired
    private IMetaDataSetService metaDataSetService;

    @Cacheable( value="entitymodel",key = "'row:'+#p0+'.'+#p1")
    public EntityModel getEntityModel(String systemId, String name)
    {
        MetaEntity entity = LiteStorage.getMetaEntity(String.format("%1$s.%2$s",systemId,name));

        EntityModel entityModel = new EntityModel();
        entityModel.setEntity(entity);
        entityModel.setDataSets(metaDataSetService.selectByEntityId(entity.getEntityId()));

        Map<String, RelationshipModel> parentSet = new LinkedHashMap();
        List<RelationshipModel> references = new ArrayList<>();
        metaRelationshipService.selectByEntityId(entity.getEntityId()).forEach(item->
        {
            RelationshipModel model = new RelationshipModel();
            MetaEntity parentEntity = LiteStorage.getMetaEntity(item.getRefEntityId());
            if(parentEntity!=null){
                model.setCodeName(item.getCodeName());
                model.setDataSourceName(parentEntity.getDsName());
                model.setEntityCodeName(parentEntity.getCodeName());
                model.setEntityId(parentEntity.getEntityId());
                model.setEntityLogicName(parentEntity.getLogicName());
                model.setEntityName(parentEntity.getEntityName());
                model.setSystemId(parentEntity.getSystemId());
                model.setTableName(parentEntity.getTableName());
                parentSet.put(item.getId(),model);
                references.add(model);
            }
        });
        entityModel.setReferences(references);

        List<RelationshipModel> nesteds = new ArrayList<>();
        metaRelationshipService.selectByRefEntityId(entity.getEntityId()).forEach(item->
        {
            RelationshipModel model = new RelationshipModel();
            MetaEntity subEntity = LiteStorage.getMetaEntity(item.getEntityId());
            if(subEntity!=null){
                model.setCodeName(StringUtils.isEmpty(item.getNestedName())?item.getCodeName()+"_"+item.getEntityName():item.getNestedName());
                model.setDataSourceName(subEntity.getDsName());
                model.setEntityCodeName(subEntity.getCodeName());
                model.setEntityId(subEntity.getEntityId());
                model.setEntityLogicName(subEntity.getLogicName());
                model.setEntityName(subEntity.getEntityName());
                model.setSystemId(subEntity.getSystemId());
                model.setTableName(subEntity.getTableName());
                nesteds.add(model);
            }
        });
        entityModel.setNesteds(nesteds);

        List<FieldModel> fields = new ArrayList<>();
        metaFieldService.selectByEntityId(entity.getEntityId()).forEach(item->
        {
            FieldModel model = new FieldModel();
            model.setField(item);
            model.setCodeName(item.getCodeName());
            model.setColumnName(item.getFieldName());
            model.setComment(item.getFieldLogicName());
            model.setShowName(item.getFieldShowName());
            model.setUnionName(item.getFieldUniName());
            if((!StringUtils.isEmpty(item.getRelationId()))&&(parentSet.containsKey(item.getRelationId())))
                model.setReference(parentSet.get(item.getRelationId()));
            fields.add(model);
        });
        entityModel.setFields(fields);


        return entityModel;
    }

    @CacheEvict( value="entitymodel",key = "'row:'+#p0+'.'+#p1")
    public void resetEntityModel(String systemId, String name)
    {
        LiteStorage.resetMetaEntity(String.format("%1$s.%2$s",systemId,name));
    }


    public void initMetaEntity()
    {
        metaEntityService.list().forEach(metaEntity -> {
            LiteStorage.putMetaEntity(metaEntity);
        });
    }


}
