package com.tykj.workflowcore.model.service;

import com.tykj.workflowcore.base.result.ApiException;
import com.tykj.workflowcore.model.entity.ColumnInfo;
import com.tykj.workflowcore.model.entity.Quote;
import com.tykj.workflowcore.model.entity.TableInfo;
import com.tykj.workflowcore.model.repository.BindRepository;
import com.tykj.workflowcore.model.repository.ColumnInfoRepository;
import com.tykj.workflowcore.model.repository.QuoteRepository;
import com.tykj.workflowcore.model.repository.TableInfoRepository;
import com.tykj.workflowcore.workflow_editer.entity.FlowsInfo;
import com.tykj.workflowcore.workflow_editer.service.FormPageService;
import com.tykj.workflowcore.workflow_editer.service.WorkFlowService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;

@SuppressWarnings("Duplicates")
@Service
public class TableInfoService {

    @Autowired
    private TableInfoExService tableInfoExService;
    @Autowired
    private TableInfoRepository tableInfoRepository;
    @Autowired
    private ColumnInfoRepository columnInfoRepository;
    @Autowired
    private QuoteRepository quoteRepository;
    @Autowired
    private FormPageService formPageService;
    @Autowired
    private BindRepository bindRepository;

    public void save(TableInfo tableInfo) {
        //数据检查
        boolean exists = tableInfoRepository.existsByName(tableInfo.getName());
        if (exists) {
            throw new RuntimeException("该模型已存在");
        }
        if (nonNull(tableInfo.getId())) {
            throw new RuntimeException("新增操作不可附带id");
        }
        //设置时间
        Date date = new Date();
        tableInfo.setCreatedTime(date);
        tableInfo.setUpdatedTime(date);
        //设置版本号
        tableInfo.setVersion(1);
        //保存数据
        Integer tableInfoId = tableInfoRepository.save(tableInfo).getId();
        if (nonNull(tableInfo.getColumnInfos())) {
            tableInfo.getColumnInfos().forEach(columnInfo -> saveColumnInfo(columnInfo, tableInfoId));
        }
    }

    public void update(TableInfo tableInfo) {
        //数据检查
        boolean exists = tableInfoRepository.existsByName(tableInfo.getName());
        if (!exists) {
            throw new RuntimeException("该模型不存在");
        }
        if (nonNull(tableInfo.getId())) {
            throw new RuntimeException("修改操作不可附带id");
        }
        //检查是否已经在运行中
        formPageService.checkIfWorking(tableInfo.getProcessKey());
        //设置时间
        Date date = new Date();
        tableInfo.setCreatedTime(date);
        tableInfo.setUpdatedTime(date);
        //设置版本号
        Integer count = tableInfoRepository.countByName(tableInfo.getName());
        tableInfo.setVersion(count + 1);
        //保存数据
        Integer tableInfoId = tableInfoRepository.save(tableInfo).getId();
        if (nonNull(tableInfo.getColumnInfos())) {
            tableInfo.getColumnInfos().forEach(columnInfo -> saveColumnInfo(columnInfo, tableInfoId));
        }
        //更新有关联的聚合对象
        tableInfoExService.updateRelatedTableInfoEx(tableInfo);
    }

    public TableInfo findByNameAndVersion(String name, Integer version) {
        TableInfo tableInfo = tableInfoRepository.findByNameAndVersion(name, version);
        if (isNull(tableInfo)) {
            throw new RuntimeException("该模型不存在");
        }
        List<ColumnInfo> columnInfos = columnInfoRepository.findByTableInfoId(tableInfo.getId());
        tableInfo.setColumnInfos(columnInfos);
        return tableInfo;
    }

    public List<TableInfo> findAll() {
        return tableInfoRepository.findAll().stream()
                .map(TableInfo::getName)
                .distinct()
                .map(this::findLastVersion)
                .collect(Collectors.toList());
    }

    public void deleteByName(String name) {
        boolean hasBind = bindRepository.existsByName(name);
        if (hasBind){
            throw new RuntimeException("该模型已在聚合模型中绑定");
        }
        List<TableInfo> tableInfos = tableInfoRepository.findByName(name);
        for (TableInfo tableInfo : tableInfos) {
            Integer tableInfoId = tableInfo.getId();
            List<ColumnInfo> columnInfos = columnInfoRepository.findByTableInfoId(tableInfoId);
            for (ColumnInfo columnInfo : columnInfos) {
                Integer columnInfoId = columnInfo.getId();
                quoteRepository.deleteAllByColumnInfoId(columnInfoId);
                columnInfoRepository.deleteById(columnInfoId);
            }
            tableInfoRepository.deleteById(tableInfoId);
        }
    }

    public TableInfo findLastVersion(String name) {
        return tableInfoRepository.findByName(name).stream()
                .max(Comparator.comparingInt(TableInfo::getVersion))
                .map(this::getColumnInfos)
                .orElseThrow(() -> new RuntimeException("查询失败"));
    }

    //-----------------------------------------------------------------------------//

    private void saveColumnInfo(ColumnInfo columnInfo, Integer tableInfoId) {
        columnInfo.setTableInfoId(tableInfoId);
        Integer columnInfoId = columnInfoRepository.save(columnInfo).getId();
        if (nonNull(columnInfo.getQuotes())) {
            columnInfo.getQuotes().forEach(quote -> saveQuote(quote, columnInfoId));
        }
    }

    private void saveQuote(Quote quote, Integer columnInfoId) {
        quote.setColumnInfoId(columnInfoId);
        quoteRepository.save(quote);
    }

    private TableInfo getColumnInfos(TableInfo tableInfo) {
        List<ColumnInfo> columnInfos = columnInfoRepository.findByTableInfoId(tableInfo.getId()).stream()
                .map(this::getQuotes)
                .collect(Collectors.toList());
        tableInfo.setColumnInfos(columnInfos);
        return tableInfo;
    }

    private ColumnInfo getQuotes(ColumnInfo columnInfo) {
        List<Quote> quotes = quoteRepository.findByColumnInfoId(columnInfo.getId());
        columnInfo.setQuotes(quotes);
        return columnInfo;
    }

}
