package com.sw.mes.plan.controller;

import com.sw.mes.base.factory.init.entity.MachineCapacityKf;
import com.sw.mes.base.factory.init.service.MachineCapacityKfService;
import com.sw.mes.base.factory.material.entity.MaterialModel;
import com.sw.mes.core.annotation.TokenNotValidation;
import com.sw.mes.core.dto.FbDeviceSchedule;
import com.sw.mes.core.dto.FbDeviceScheduleParam;
import com.sw.mes.core.dto.FbScheduleDto;
import com.sw.mes.core.dto.RankResultDto;
import com.sw.mes.core.response.ResponsePage;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.*;
import com.sw.mes.enumvalue.EnumValuesFbServer;
import com.sw.mes.fb.checkout.service.FbCheckOutDataService;
import com.sw.mes.fb.turnstore.entity.FbTurnstoreTrayItem;
import com.sw.mes.fb.turnstore.service.FbTurnstoreTrayItemService;
import com.sw.mes.plan.dto.BatchSchedulingDto;
import com.sw.mes.plan.dto.MatchOrderInfo;
import com.sw.mes.plan.dto.ProductionScheduleDto;
import com.sw.mes.plan.dto.SchedulingInfoDto;
import com.sw.mes.plan.entity.FbProductionOrder;
import com.sw.mes.plan.entity.FbProductionSchedule;
import com.sw.mes.plan.service.FbProductionOrderService;
import com.sw.mes.plan.service.FbProductionScheduleService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@RestController
@RequestMapping("/fb/productionSchedule")
@Slf4j
@Api(description = "圆棒工单排程接口")
public class FbProductionScheduleController {
    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private FbCheckOutDataService fbCheckOutDataService;

    @Autowired
    private FbProductionScheduleService productionScheduleService;

    @Autowired
    private FbProductionOrderService fbProductionOrderService;

    @Autowired
    private FbTurnstoreTrayItemService fbTurnstoreTrayItemService;

    @Autowired
    private MachineCapacityKfService machineCapacityKfService;

    @TokenNotValidation
    @GetMapping("/data")
    public String listByPage(@RequestParam("passWord") String passWord, @RequestParam("trayNo") String trayNo,
                             ServletResponse response) throws IOException, InterruptedException {
        if (StringUtils.isBlank(passWord)) {
            return "<b style='color: red'>密码不能为空<b/>";
        }
        if (!"gj123654".equals(passWord)) {
            return "<b style='color: red'>密码错误<b/>";
        }
        if (StringUtils.isBlank(trayNo)) {
            return "<b style='color: red'>托号不能为空<b/>";
        }
        List<FbTurnstoreTrayItem> fbTurnstoreTrayItem = fbTurnstoreTrayItemService.getData(trayNo);
        if (fbTurnstoreTrayItem.size() == 0) {
            return "<b style='color: red'>该托号不存在<b/>";
        }
        for (FbTurnstoreTrayItem fbTurnstoreTrayItem1 : fbTurnstoreTrayItem) {
            Map<String, Object> inspectMap = fbCheckOutDataService.findBySectionNoMap(fbTurnstoreTrayItem1.getSectionNo());
            //产品最终评级
            Object ybLevelObject = inspectMap.get("yb_level");
            String ybLevel = ybLevelObject == null ? null : ybLevelObject.toString();
            //产品等级
            String productLevel = NumberUtil.object2String(inspectMap.get("product_level"), null);
            if (StringUtils.isBlank(productLevel)) {
                ybLevel = productLevel;
            }
            //型号
            Object conductiveTypeObject = inspectMap.get("conduction_type");
            String conductiveType = conductiveTypeObject == null ? null : conductiveTypeObject.toString();
            //拼接
            Integer sticksCount = NumberUtil.Object2Integer(inspectMap.get("sticks_count"), null);
            // 长度
            BigDecimal length;
            if (sticksCount == 1) {
                length = NumberUtil.Object2BigDecimal(inspectMap.get("length"));
            } else {
                length = NumberUtil.Object2BigDecimal(inspectMap.get("spell_bar_length"));
            }
            Object orderTypeObject = inspectMap.get("order_type");
            String orderType = orderTypeObject == null ? null : orderTypeObject.toString();
            String checkoutName = NumberUtil.object2String(inspectMap.get("checkout_name"), null);
            Object dopantObj = inspectMap.get("dopant");
            Object specificationsObj = inspectMap.get("specification");
            String dopant = dopantObj == null ? null : dopantObj.toString(), specifications = specificationsObj == null ? null : specificationsObj.toString();
            String productLevelFb = NumberUtil.object2String(inspectMap.get("product_level_fb"), null);
            String sectionType = NumberUtil.object2String(inspectMap.get("section_type"), null);
            String sectionNo = NumberUtil.object2String(inspectMap.get("section_no"), null);
            Map<String, String> resultMaps = new HashMap<>();
            //边长
            Object sideLengthRangeObject = inspectMap.get("sideLengthRange");
            String sideLengthRange = sideLengthRangeObject == null ? null : sideLengthRangeObject.toString();
            MatchOrderInfo fbProductionOrderMap = fbProductionOrderService.matchOrder(sectionNo, ybLevel, specifications, conductiveType, dopant, sticksCount, length, orderType, checkoutName, productLevelFb, sectionType,sideLengthRange);
            String orderNoOld = fbTurnstoreTrayItem1.getOrderNo();
            String materialCodeOld = fbTurnstoreTrayItem1.getMaterialNumber();
            if (fbProductionOrderMap != null) {
                resultMaps.put("material_number", fbProductionOrderMap.getMaterialCode());
                resultMaps.put("order_no", fbProductionOrderMap.getOrderNo());
                fbTurnstoreTrayItem1.setOrderNo(fbProductionOrderMap.getOrderNo());
                fbTurnstoreTrayItem1.setMaterialNumber(fbProductionOrderMap.getMaterialCode());
            } else {
                resultMaps.put("material_number", null);
                resultMaps.put("order_no", null);
                fbTurnstoreTrayItem1.setOrderNo(null);
                fbTurnstoreTrayItem1.setMaterialNumber(null);
            }
            int index = 1, mapCount = resultMaps.size();
            StringBuilder sql = new StringBuilder();
            sql.append("UPDATE zhxx_operate_check_out_data SET ");
            for (Map.Entry<String, String> entry : resultMaps.entrySet()) {
                if (entry.getValue() == null) {
                    sql.append(entry.getKey()).append(" =").append(entry.getValue()).append(" ");
                } else {
                    sql.append(entry.getKey()).append(" ='").append(entry.getValue()).append("' ");
                }
                if (index < mapCount) {
                    sql.append(",");
                }
                index++;
            }
            sql.append(" WHERE id = ").append(inspectMap.get("id"));
            fbCheckOutDataService.excuteUpdate(sql.toString());
            fbTurnstoreTrayItemService.saveOrUpdate(fbTurnstoreTrayItem1);
            String classs1 = "<b style='color: green'>", classs2 = "<b style='color: red'>";
            String data = ((fbTurnstoreTrayItem1.getOrderNo() == null || fbTurnstoreTrayItem1.getMaterialNumber() == null) ? classs2 : classs1)
                    + fbTurnstoreTrayItem1.getSectionNo() + "-----|----[" + orderNoOld + "->" + fbTurnstoreTrayItem1.getOrderNo() + "]----|----[" + materialCodeOld + "->" + fbTurnstoreTrayItem1.getMaterialNumber() + "]</b><br/>";
            response.getOutputStream().println(data);
        }
        response.getOutputStream().close();
        return "<b style='color: green'>匹配成功</b>";
    }

    @ApiOperation(value = "分页查询圆棒工单排程列表")
    @ApiImplicitParams({@ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"), @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),})
    @GetMapping("/listByPage")
    public Result<ResponsePage<ProductionScheduleDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        Specification<FbProductionSchedule> specification = DynamicSpecifications.bySearchFilter(request, FbProductionSchedule.class);
        Page<FbProductionSchedule> page = productionScheduleService.findByExample(specification, PageUtil.createPageable(requestPage));
        List<ProductionScheduleDto> dtos = page.getContent().stream().map(entity -> toLazyDto(entity)).collect(Collectors.toList());
        for (ProductionScheduleDto dto : dtos) {
            if (dto.getCapacityId() == null) continue;
            MachineCapacityKf capacity = machineCapacityKfService.get(dto.getCapacityId());
            dto.setLengthRange(capacity.getLengthRangeMin() + "-" + capacity.getLengthRangeMax());
            dto.setSticksCount(capacity.getSticksCount());
        }
        ResponsePage responsePage = new ResponsePage(dtos, page.getTotalElements());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "获取所有圆棒工单排程")
    @GetMapping("/listAll")
    public Result<List<ProductionScheduleDto>> listAll(ServletRequest request) {
        Specification<FbProductionSchedule> specification = DynamicSpecifications.bySearchFilter(request, FbProductionSchedule.class);
        List<FbProductionSchedule> productionSchedules = productionScheduleService.findByExampleSort(specification, null);
        List<ProductionScheduleDto> productionScheduleDtos = productionSchedules.stream().map(productionSchedule -> toLazyDto(productionSchedule)).collect(Collectors.toList());
        return ResultGenerator.success(productionScheduleDtos);
    }

    @ApiOperation(value = "圆棒工单排程详细信息")
    @GetMapping("/{id}")
    public Result<ProductionScheduleDto> get(@PathVariable @ApiParam(value = "圆棒工单排程id") Integer id) {
        FbProductionSchedule productionSchedule = productionScheduleService.get(id);
        if (null == productionSchedule) return ResultGenerator.fail("该圆棒工单排程不存在");
        return ResultGenerator.success(toEagerDto(productionSchedule));
    }

    @ApiOperation(value = "创建圆棒工单排程")
    @PostMapping("/create")
    public Result create(@RequestBody @Valid @ApiParam(value = "圆棒工单排程对象") ProductionScheduleDto productionScheduleDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        FbProductionSchedule productionSchedule = fromDto(productionScheduleDto);
        productionScheduleService.saveOrUpdate(productionSchedule);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "更新圆棒工单排程")
    @PostMapping("/update")
    public Result update(@RequestBody @Valid @ApiParam(value = "圆棒工单排程") ProductionScheduleDto dto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        if (dto.getId() == null) return ResultGenerator.fail("id不能为空");
        FbProductionSchedule entity = productionScheduleService.get(dto.getId());
        if (entity == null) return ResultGenerator.fail("原信息不存在");
        try {
            FbProductionSchedule entityfromFto = fromDto(dto);
            BeanUtils.copyProperties(entityfromFto, entity, BeanUtil.getIgnoreProperties(entityfromFto, null, null));
            productionScheduleService.saveOrUpdate(entity);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    /**
     * 批量排程
     *
     * @param
     * @return
     */
    @ApiOperation(value = "批量排程")
    @PostMapping("/batchScheduling")
    public Result batchScheduling(@RequestBody @Valid @ApiParam(value = "圆棒工单批量排程") BatchSchedulingDto dto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        productionScheduleService.batchScheduling(dto);
        return ResultGenerator.success();
    }


    @ApiOperation(value = "机加自动排程")
    @GetMapping("/autoScheduling")
    public Result cutAutoScheduling(){
        productionScheduleService.autoScheduling();
        return ResultGenerator.success();
    }

    @ApiOperation(value = "机加自动关闭排程")
    @GetMapping("/autoCloseScheduling")
    public Result autoCloseScheduling(){
        productionScheduleService.autoCloseScheduling();
        return ResultGenerator.success();
    }

    /**
     * 获取设备排程情况
     *
     * @param
     * @return
     */
    @ApiOperation(value = "排程情况")
    @GetMapping("/getSchedulingInfo")
    public Result<List<SchedulingInfoDto>> getSchedulingInfo() {
        List<SchedulingInfoDto> list = productionScheduleService.getSchedulingInfo();
        return ResultGenerator.success(list);
    }

    @ApiOperation(value = "删除圆棒工单排程")
    @PostMapping("/delete")
    public Result remove(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids) {
        for (Integer id : ids) {
            productionScheduleService.delete(id);
        }
        return ResultGenerator.success();
    }

    public ProductionScheduleDto toLazyDto(FbProductionSchedule entity) {
        return modelMapper.map(entity, ProductionScheduleDto.class);
    }

    public ProductionScheduleDto toEagerDto(FbProductionSchedule entity) {
        ProductionScheduleDto dto = modelMapper.map(entity, ProductionScheduleDto.class);
        return dto;
    }

    public FbProductionSchedule fromDto(ProductionScheduleDto dto) {
        return modelMapper.map(dto, FbProductionSchedule.class);
    }

    /**
     * 圆棒匹配方棒加工订单
     *
     * @param specs          规格
     * @param conductiveType 导电型号
     * @param dopant         掺杂剂
     * @param productLevel   产品等级
     * @return 方棒订单号
     */
    @ApiOperation(value = "根据圆棒属性匹配，可以生产的排产方棒订单号")
    @GetMapping("/findProductionScheduleCode")
    public Result<String> findProductionScheduleCode(@RequestParam("specs") String specs, @RequestParam("conductiveType") String conductiveType, @RequestParam("dopant") String dopant, @RequestParam("productLevel") String productLevel) {
        String orderCode = productionScheduleService.findProductionScheduleCode(specs, conductiveType, dopant, productLevel);
        return ResultGenerator.success(orderCode);
    }


    /**
     * 圆棒匹配方棒加工订单
     *
     * @return 方棒订单号
     */
    @ApiOperation(value = "根据圆棒属性匹配，可以生产的排产方棒订单号")
    @PostMapping("/findProductionScheduleCodePro")
    public Result<String> findProductionScheduleCodePro(@RequestBody RankResultDto rankResultDto) {
        String orderCode = productionScheduleService.findProductionScheduleCodePro(rankResultDto);
        return ResultGenerator.success(orderCode);
    }


    /**
     * @param fbDeviceScheduleParam
     * @return
     */
    @ApiOperation(value = "根据圆棒属性匹配，可以生产的排产方棒订单号")
    @PostMapping("/findFbDeviceSchedule")
    public Result<FbDeviceSchedule> findFbDeviceSchedule(@RequestBody FbDeviceScheduleParam fbDeviceScheduleParam) {
        FbDeviceSchedule fbDeviceSchedule = productionScheduleService.findFbDeviceSchedule(fbDeviceScheduleParam);
        return ResultGenerator.success(fbDeviceSchedule);
    }


    /**
     * 根据设备编号查询排程
     */
    @ApiOperation(value = "根据设备编号查询排程")
    @GetMapping("/findByDeviceNo")
    public Result<FbScheduleDto> findProductionScheduleCode(@RequestParam("deviceNo") String deviceNo) {
        FbProductionSchedule schedule = productionScheduleService.findByDeviceNoAndStatus(deviceNo, EnumValuesFbServer.ProductionScheduleStatus.进行中.getKey());
        if (ObjectUtils.isEmpty(schedule)) return ResultGenerator.fail("未查询到对应排程信息");
        FbScheduleDto dto = new FbScheduleDto();
        dto.setDeviceNo(deviceNo);

        FbProductionOrder productionOrder = schedule.getProductionOrder();
        if (null != productionOrder){
            dto.setMatnr(productionOrder.getMatnr());
            dto.setMeins(productionOrder.getMeins());
            dto.setOrderNo(productionOrder.getAufnr());
            MaterialModel materialModel = productionOrder.getMaterialModel();
            if (null != productionOrder.getMaterialModel()){
                dto.setMaterialModelCode(materialModel.getCode());
                dto.setMaterialModelId(materialModel.getId());
                dto.setMaterialModelName(materialModel.getName());
                if (null != materialModel.getMaterialType()){
                    dto.setMaterialTypeName(materialModel.getMaterialType().getName());
                }
            }
            dto.setSupplier(materialModel.getSupplier());
            dto.setSpecification(materialModel.getSpecification());
            dto.setMaterialTh(materialModel.getNumberOfDrawings());
            if (null != materialModel.getUnit()){
                dto.setUnitName(materialModel.getUnit().getName());
            }
            dto.setSupplierCode(materialModel.getSupplier());
        }
        return ResultGenerator.success(dto);
    }
}
