package easydo.technology.controller;

import easydo.technology.components.JdbcClient;
import easydo.technology.enums.MESEnum;
import easydo.technology.exception.BizException;
import easydo.technology.model.ProcessRoute;
import easydo.technology.model.ProcessRouteDetail;
import easydo.technology.model.ProcessStage;
import easydo.technology.service.FlowNoService;
import easydo.technology.utils.SecurityUtils;
import easydo.technology.utils.StringUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/processRoute")
public class ProcessRouteController {
    @Resource
    JdbcClient jdbcClient;
    @Resource
    DataSource dataSource;
    @Resource
    FlowNoService flowNoService;

    @RequestMapping(value = "/getList")
    public Object getList(@RequestBody Map<String, Object> map) throws Exception {
        List<ProcessRoute> list = jdbcClient.getJdbcList(map, ProcessRoute.class);
        return new ResponseEntity<>(list, HttpStatus.OK);
    }

    @RequestMapping(value = "/getPage")
    public Object getPage(@RequestBody Map<String, Object> map) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            Map<String, Object> recordsPage = jdbcClient.getJdbcPage(map, ProcessRoute.class, connection);
            List<ProcessRoute> records = (List<ProcessRoute>) recordsPage.get("records");
            for (ProcessRoute model : records) {
                ProcessRouteDetail routeDetail = new ProcessRouteDetail();
                routeDetail.setRouteId(model.getId());
                List<ProcessRouteDetail> routeDetailList = jdbcClient.getJdbcList(routeDetail, connection);
                for (ProcessRouteDetail detail : routeDetailList) {
                    ProcessStage stage = new ProcessStage();
                    stage.setId(detail.getStageId());
                    stage = jdbcClient.getJdbcModelById(stage, connection);
                    detail.setStage(stage);
                }
                model.setDetailList(routeDetailList);

                jdbcClient.getMinioFile(model, connection);

                ProcessRoute child = new ProcessRoute();
                child.setParentId(model.getId());
                int count = jdbcClient.getJdbcCount(child, connection);
                if (count > 0) {
                    model.setIsHaveHistory(true);
                } else {
                    model.setIsHaveHistory(false);
                }
            }
            return new ResponseEntity<>(recordsPage, HttpStatus.OK);
        } catch (Exception e) {
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }


    @RequestMapping(value = "/save")
    public Object save(@RequestBody ProcessRoute model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);
            model.setCreateId(SecurityUtils.getCurrentUserId());
            generateCode(model, connection);
            model.setParentId("0");
            model.setStatus(MESEnum.PROCESS_OF_STATUS_ENABLE.getValue());
            jdbcClient.jdbcInsert(model, connection);

            List<ProcessRouteDetail> detailList = model.getDetailList();
            for (ProcessRouteDetail detail : detailList) {
                detail.setRouteId(model.getId());
                jdbcClient.jdbcInsert(detail, connection);
            }
            connection.commit();
            return new ResponseEntity<>(model, HttpStatus.OK);
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    @RequestMapping(value = "/update")
    public Object update(@RequestBody ProcessRoute model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);
            jdbcClient.jdbcUpdateById(model, connection);

            List<ProcessRouteDetail> detailList = model.getDetailList();
            if (null != detailList && !detailList.isEmpty()) {
                ProcessRouteDetail routeDetail = new ProcessRouteDetail();
                routeDetail.setRouteId(model.getId());
                jdbcClient.jdbcRemove(routeDetail, connection);

                for (ProcessRouteDetail detail : detailList) {
                    detail.setRouteId(model.getId());
                    jdbcClient.jdbcInsert(detail, connection);
                }
            }
            connection.commit();
            return new ResponseEntity<>(model, HttpStatus.OK);
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    @RequestMapping(value = "/remove")
    public Object remove(@RequestBody ProcessRoute model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);
            jdbcClient.jdbcRemoveById(model, connection);

            ProcessRouteDetail routeDetail = new ProcessRouteDetail();
            routeDetail.setRouteId(model.getId());
            jdbcClient.jdbcRemove(routeDetail, connection);

            ProcessRoute history = new ProcessRoute();
            history.setParentId(model.getId());
            List<ProcessRoute> historyList = jdbcClient.getJdbcList(history, connection);
            for (ProcessRoute hismodel : historyList) {
                jdbcClient.jdbcRemoveById(hismodel, connection);

                ProcessRouteDetail routeHisDetail = new ProcessRouteDetail();
                routeHisDetail.setRouteId(hismodel.getId());
                jdbcClient.jdbcRemove(routeHisDetail, connection);
            }

            connection.commit();
            return new ResponseEntity<>(model, HttpStatus.OK);
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    @RequestMapping(value = "/upgrade")
    public Object upgrade(@RequestBody ProcessRoute model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);
            String newId = UUID.randomUUID().toString();

            ProcessRoute existRoute = new ProcessRoute();
            existRoute.setId(model.getId());
            existRoute.setParentId(newId);
            existRoute.setStatus(MESEnum.PROCESS_OF_STATUS_DISABLE.getValue());
            jdbcClient.jdbcUpdateById(existRoute, connection);

            ProcessRoute childrenRoute = new ProcessRoute();
            childrenRoute.setParentId(newId);
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("parentId", model.getId());
            jdbcClient.jdbcUpdate(childrenRoute, paramMap, connection);

            model.setCreateId(SecurityUtils.getCurrentUserId());
            generateCode(model,connection);
            model.setParentId("0");
            model.setId(newId);
            model.setStatus(MESEnum.PROCESS_OF_STATUS_ENABLE.getValue());
            jdbcClient.jdbcInsert(model, connection);

            List<ProcessRouteDetail> detailList = model.getDetailList();
            for (ProcessRouteDetail detail : detailList) {
                detail.setRouteId(model.getId());
                jdbcClient.jdbcInsert(detail, connection);
            }
            connection.commit();
            return new ResponseEntity<>(model, HttpStatus.OK);
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    @RequestMapping(value = "/regrade")
    public Object regrade(@RequestBody ProcessRoute model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);
            ProcessRoute children = new ProcessRoute();
            children.setParentId(model.getId());
            List<ProcessRoute> childrenList = jdbcClient.getJdbcList(children, connection);
            if (!childrenList.isEmpty()) {
                childrenList = childrenList.stream().sorted(Comparator.comparing(ProcessRoute::getCreateTime).reversed()).collect(Collectors.toList());
                ProcessRoute child = childrenList.get(0);
                child.setParentId("0");
                child.setStatus(MESEnum.PROCESS_OF_STATUS_ENABLE.getValue());
                jdbcClient.jdbcUpdateById(child, connection);

                ProcessRoute childrenRoute = new ProcessRoute();
                childrenRoute.setParentId(child.getId());
                Map<String, Object> paramMap = new HashMap<>();
                paramMap.put("parentId", model.getId());
                jdbcClient.jdbcUpdate(childrenRoute, paramMap, connection);

                jdbcClient.jdbcRemoveById(model, connection);

                ProcessRouteDetail routeDetail = new ProcessRouteDetail();
                routeDetail.setRouteId(model.getId());
                jdbcClient.jdbcRemove(routeDetail, connection);
            }
            connection.commit();
            return new ResponseEntity<>(model, HttpStatus.OK);
        } catch (Exception e) {
            connection.rollback();
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }

    private synchronized void generateCode(ProcessRoute model, Connection connection) throws Exception {
        if (StringUtil.isEmpty(model.getCode())) {
            while (true) {
                String flowNo = flowNoService.getFlowNo(MESEnum.FLOW_NO_TYPE_PROCESS_ROUTE.getValue(), connection);
                ProcessRoute processRouteParam = new ProcessRoute();
                processRouteParam.setCode(flowNo);
                int count = jdbcClient.getJdbcCount(processRouteParam, connection);
                if (count == 0) {
                    model.setCode(flowNo);
                    break;
                }
            }
        } else {
            ProcessRoute processRouteParam = new ProcessRoute();
            processRouteParam.setCode(model.getCode());
            int count = jdbcClient.getJdbcCount(processRouteParam, connection);
            if (count > 0) {
                throw new BizException("编号已存在，请重新填写");
            }
        }
    }

}
