package com.tykj.workflowcore.model_layer.service.impl;

import com.tykj.workflowcore.base.result.ApiException;

import com.tykj.workflowcore.model_layer.dao.AggregationDao;
import com.tykj.workflowcore.model_layer.dao.TableInfoDao;
import com.tykj.workflowcore.model_layer.dao.TableInfoExDao;

import com.tykj.workflowcore.model_layer.entity.Aggregation;
import com.tykj.workflowcore.model_layer.entity.TableInfo;
import com.tykj.workflowcore.model_layer.entity.TableInfoEx;
import com.tykj.workflowcore.model_layer.entity.vo.AggregationVO;
import com.tykj.workflowcore.model_layer.myEnum.AggregationType;
import com.tykj.workflowcore.model_layer.service.AggregationService;
import com.tykj.workflowcore.model_layer.utils.AggregationUtil;
import com.tykj.workflowcore.model_layer.utils.SessionUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;


import javax.transaction.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * @ClassName AggregationImpl
 * @Description TODO
 * @Author WWW
 * @Date 2021/4/1 17:24
 * @Version 1.0
 */
@Service
public class AggregationImpl implements AggregationService {

    @Autowired
    TableInfoDao tableInfoDao;
    @Autowired
    TableInfoExDao tableInfoExDao;
    @Autowired
    AggregationDao aggregationRelationshipDao;
    @Autowired
    SessionUtil sessionUtil;

    @Override
    @Transactional(rollbackOn = Exception.class)
    public void addAggregation(AggregationVO aggregationVO) {
        Document mainTableDocument;
        //获取主表XML
        Integer mainTableId = aggregationVO.getMainTableId();
        Optional<TableInfo> mainTableById = tableInfoDao.findById(mainTableId);
        if (mainTableById.isPresent()){
            mainTableDocument = AggregationUtil.getDocument(mainTableById.get().getXml());
        }else {
            throw new ApiException("主表不存在");
        }
        //改CLASS名字
        AggregationUtil.changeClassName(aggregationVO.getName(),mainTableDocument );
        // save TableInfoEx  （name des mainTableId）
        TableInfoEx tableInfoEx = tableInfoExDao.save(aggregationVO.getTableInfoEx());
        try {
            createAggregationObjectXml(aggregationVO.getAggregations(), null, tableInfoEx.getId(), mainTableById.get(), mainTableDocument.getRootElement());
            tableInfoEx.setXml(mainTableDocument.asXML());
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        tableInfoExDao.save(tableInfoEx);
    }

    //假设获得的是一份XML
    public  Element createAggregationObjectXml(List<Aggregation> aggregations, Aggregation parentAggregation, Integer tableInfoExId, TableInfo mainTableInfo, Element rootElement) throws DocumentException {
        //这里需要一个class标签，
        Boolean isFirst = false;
        Element elementClass ;
        String parentModeName;
        if (parentAggregation!=null){
            //如果不是第一层,则通过parentAggregation,查出副表的XML字符串
            //将XML字符串转换为XML对象
            //取出Class标签,将Class标签赋值给elementClass
            Optional<TableInfo> sideTableInfoOptional = tableInfoDao.findById(parentAggregation.getSideTableId());
            if (sideTableInfoOptional.isPresent()){
                elementClass  = (Element) DocumentHelper.parseText(sideTableInfoOptional.get().getXml()).getRootElement().element("class").clone();
            }else {
                throw new ApiException("id为："+parentAggregation.getSideTableId()+"的副表不存在");
            }
            parentModeName = sideTableInfoOptional.get().getModelName();
        }else {
            //如果是第一层 则通过rootElement 查出副表的XML字符串
            //取出Class标签,将Class标签赋值给elementClass
            elementClass = (Element) rootElement.element("class");
            parentModeName = mainTableInfo.getModelName();
            isFirst = true;
        }
        //循环
        for (int i = 0; i < aggregations.size(); i++) {
            Aggregation aggregationChild = aggregations.get(i);
            if (aggregationChild.getAggregations()!=null&&aggregationChild.getAggregations().size()>0){
                String uuid ="tykj"+UUID.randomUUID().toString().replaceAll("-","");
                Element elementClassChild = createAggregationObjectXml(aggregationChild.getAggregations(), aggregationChild, tableInfoExId, mainTableInfo,rootElement);
                //为element给一个UUID的entity_name
                aggregationChild.setUuidTableName(uuid);
                elementClassChild.attribute("entity-name").setValue(uuid);
                Element elementSet = aggregationToXmlElement(aggregationChild, tableInfoExId, parentModeName);
                elementClass.add(elementSet);
            }else {
                //addSet
                Element elementSet = aggregationToXmlElement(aggregationChild, tableInfoExId, parentModeName);
                elementClass.add(elementSet);
            }
            aggregationRelationshipDao.save(aggregationChild);
        }
        if (!isFirst){
            rootElement.add(elementClass);
        }
        return elementClass;
    }

    public Element aggregationToXmlElement(Aggregation aggregation,Integer tableInfoExId,String parentModelName){
        //设置tableInfoExId
        aggregation.setTableInfoExId(tableInfoExId);

        Optional<TableInfo> sideTableById = tableInfoDao.findById(aggregation.getSideTableId());
        if (!sideTableById.isPresent()){
            throw new ApiException("id为："+aggregation.getSideTableId()+"的副表不存在");
        }
        if (aggregation.getRelationship().equals(AggregationType.ONE_TO_ONE)){
            return AggregationUtil.createOneToOneElement(
                    sideTableById.get().getModelName(),
                    aggregation.getSideTableConnectionKey(),
                    StringUtils.isEmpty(aggregation.getUuidTableName())?sideTableById.get().getModelName():aggregation.getUuidTableName()
                    );
        }
        if (aggregation.getRelationship().equals(AggregationType.ONE_TO_MANY)){
            return AggregationUtil.createOneToManyElement(
                    sideTableById.get().getModelName(),
                    StringUtils.isEmpty(aggregation.getUuidTableName())?sideTableById.get().getModelName():aggregation.getUuidTableName(),
                    aggregation.getSideTableConnectionKey());
        }
        if (aggregation.getRelationship().equals(AggregationType.MANY_TO_MANY)){
            //如果是多对多需要 为 aggregationRelationship 生成连接的KEY
            String mainTableConnectionKey = parentModelName+"_Id";
            String sideTableConnectionKey = sideTableById.get().getModelName()+"_Id";
            aggregation.setMainTableConnectionKey(mainTableConnectionKey);
            aggregation.setSideTableConnectionKey(sideTableConnectionKey);
            //如果是多对多需要 为 aggregationRelationship 生成连接的中间表名
            String connectionTableName = parentModelName+"_"+sideTableById.get().getModelName()+"_"+ (UUID.randomUUID().toString().substring(0,8));
            aggregation.setConnectionTableName(connectionTableName);
            //Util.addManyToMany
            return AggregationUtil.createManyToManyElement(sideTableById.get().getModelName(),aggregation.getUuidTableName(),connectionTableName,mainTableConnectionKey,sideTableConnectionKey);
        }
        return null;
    }

}
