package easydo.technology.controller;

import easydo.technology.components.JdbcClient;
import easydo.technology.enums.MESEnum;
import easydo.technology.exception.BizException;
import easydo.technology.model.ProductBom;
import easydo.technology.model.ProductMaterial;
import easydo.technology.service.FlowNoService;
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.List;
import java.util.Map;
import java.util.stream.Collectors;

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

    @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, ProductBom.class, connection);
            List<ProductBom> records = (List<ProductBom>) recordsPage.get("records");
            for (ProductBom model : records) {
                ProductMaterial material = new ProductMaterial();
                material.setCode(model.getMaterialCode());
                material = jdbcClient.getJdbcModel(material, connection);
                model.setMaterial(material);

                ProductBom param = new ProductBom();
                param.setParentId(model.getId());
                int count = jdbcClient.getJdbcCount(param, connection);
                if (count > 0) {
                    model.setIsHaveChildren(true);
                }
            }

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

    @RequestMapping(value = "/getChildrenList")
    public Object getChildrenList(@RequestBody ProductBom model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            ProductBom detail = new ProductBom();
            detail.setParentId(model.getId());
            List<ProductBom> detailList = jdbcClient.getJdbcList(detail, connection);
            model.setChildrenList(detailList);

            for (ProductBom bomDetail : detailList) {
                ProductMaterial material = new ProductMaterial();
                material.setCode(bomDetail.getMaterialCode());
                material = jdbcClient.getJdbcModel(material, connection);
                bomDetail.setMaterial(material);

                ProductBom param = new ProductBom();
                param.setParentId(bomDetail.getId());
                int count = jdbcClient.getJdbcCount(param, connection);
                if (count > 0) {
                    bomDetail.setIsHaveChildren(true);
                }
            }
            return new ResponseEntity<>(detailList, HttpStatus.OK);
        } catch (Exception e) {
            throw new BizException(e.getMessage());
        } finally {
            connection.close();
        }
    }


    @RequestMapping(value = "/save")
    public Object save(@RequestBody ProductBom model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);

            List<ProductBom> bomList = model.getChildrenList();
            if (bomList.isEmpty()) {
                return new ResponseEntity<>(model, HttpStatus.OK);
            }
            model.setStatus(MESEnum.PROCESS_OF_STATUS_ENABLE.getValue());
            if (StringUtil.isEmpty(model.getId())) {
                generateCode(model, connection);
                jdbcClient.jdbcInsert(model, connection);
            }

            for (ProductBom bom : bomList) {
                bom.setParentId(model.getId());
                jdbcClient.jdbcInsert(bom, 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 ProductBom model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);

            jdbcClient.jdbcUpdateById(model, connection);

            List<ProductBom> bomList = model.getChildrenList();
            if (bomList.isEmpty()) {
                connection.commit();
                return new ResponseEntity<>(model, HttpStatus.OK);
            }
            ProductBom param = new ProductBom();
            param.setParentId(model.getId());
            List<ProductBom> existList = jdbcClient.getJdbcList(param, connection);
            List<String> removeIdList = existList.stream().map(ProductBom::getId).collect(Collectors.toList());

            List<ProductBom> insertList = bomList.stream().filter(item -> StringUtil.isEmpty(item.getId())).collect(Collectors.toList());
            List<ProductBom> updateList = bomList.stream().filter(item -> StringUtil.isNotEmpty(item.getId())).collect(Collectors.toList());
            List<String> updateIdList = updateList.stream().map(ProductBom::getId).collect(Collectors.toList());
            removeIdList.removeAll(updateIdList);

            for (ProductBom bom : insertList) {
                bom.setParentId(model.getId());
                jdbcClient.jdbcInsert(bom, connection);
            }
            for (ProductBom bom : updateList) {
                jdbcClient.jdbcUpdateById(bom, connection);
            }
            for (String id : removeIdList) {
                ProductBom bom = new ProductBom();
                bom.setId(id);
                jdbcClient.jdbcRemoveById(bom, 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 ProductBom model) throws Exception {
        Connection connection = dataSource.getConnection();
        try {
            connection.setAutoCommit(false);
            jdbcClient.jdbcRemoveById(model, 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(ProductBom model, Connection connection) throws Exception {
        if (StringUtil.isEmpty(model.getBomCode())) {
            while (true) {
                String flowNo = flowNoService.getFlowNo(MESEnum.FLOW_NO_TYPE_PRODUCT_BOM.getValue(), connection);
                ProductBom processBomParam = new ProductBom();
                processBomParam.setBomCode(flowNo);
                int count = jdbcClient.getJdbcCount(processBomParam, connection);
                if (count == 0) {
                    model.setBomCode(flowNo);
                    break;
                }
            }
        } else {
            ProductBom processBomParam = new ProductBom();
            processBomParam.setBomCode(model.getBomCode());
            int count = jdbcClient.getJdbcCount(processBomParam, connection);
            if (count > 0) {
                throw new BizException("编号已存在，请重新填写");
            }
        }
    }
}
