package com.sw.mes.yb.production.controller;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.ServletRequest;
import javax.validation.Valid;

import com.sw.mes.yb.production.dto.CallTakeCrystalAgvDto;
import com.sw.mes.yb.production.entity.LongCrystal;
import com.sw.mes.yb.production.service.LongCrystalService;
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.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.sw.mes.base.system.entity.DictionaryItem;
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.base.system.service.DictionaryItemService;
import com.sw.mes.core.utils.BeanUtil;
import com.sw.mes.core.utils.DynamicSpecifications;
import com.sw.mes.core.utils.PageUtil;
import com.sw.mes.core.utils.RequestPage;
import com.sw.mes.yb.agv.dto.AgvCallBackParamDto;
import com.sw.mes.yb.production.dto.InspectionRecord.InspectionBackDto;
import com.sw.mes.yb.production.dto.InspectionRecord.InspectionRecordDto;
import com.sw.mes.yb.production.entity.InspectionRecord;
import com.sw.mes.yb.production.service.InspectionRecordService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.annotations.ApiIgnore;

/**
 * @Author @Description：
 * @Date: Create in
 * @Modified By:
 */
@RestController
@RequestMapping("/productionInspectionRecord")
@Slf4j
@Api(description = "送验记录接口")
public class InspectionRecordController {
    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private InspectionRecordService inspectionRecordService;
    @Autowired
    private DictionaryItemService dictionaryItemService;

    @Autowired
    private LongCrystalService longCrystalService;

    @ApiOperation(value = "分页查询送验记录列表")
    @ApiImplicitParams({ @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"), })
    @GetMapping("/listByPage")
    public Result<ResponsePage<InspectionRecordDto>> listByPage(ServletRequest request,
            @ApiIgnore RequestPage requestPage) {
        Specification<InspectionRecord> specification = DynamicSpecifications.bySearchFilter(request,
                InspectionRecord.class);
        Page<InspectionRecord> page = inspectionRecordService.findByExample(specification,
                PageUtil.createPageable(requestPage, new String[] { "inspectionTime DESC" }));
        List<InspectionRecordDto> dtos = page.getContent().stream().map(entity -> toLazyDto(entity))
                .collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, page.getTotalElements());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "获取所有送验记录")
    @GetMapping("/listAll")
    public Result<List<InspectionRecordDto>> listAll(ServletRequest request) {
        Specification<InspectionRecord> specification = DynamicSpecifications.bySearchFilter(request,
                InspectionRecord.class);
        List<InspectionRecord> inspectionRecords = inspectionRecordService.findByExampleSort(specification, null);
        List<InspectionRecordDto> inspectionRecordDtos = inspectionRecords.stream()
                .map(inspectionRecord -> toLazyDto(inspectionRecord)).collect(Collectors.toList());
        return ResultGenerator.success(inspectionRecordDtos);
    }

    @ApiOperation(value = "送验记录详细信息")
    @GetMapping("/{id}")
    public Result<InspectionRecordDto> get(@PathVariable @ApiParam(value = "送验记录id") Long id) {
        InspectionRecord inspectionRecord = inspectionRecordService.get(id);
        if (null == inspectionRecord) {
            return ResultGenerator.fail("该送验记录不存在");
        }
        return ResultGenerator.success(toEagerDto(inspectionRecord));
    }

    @ApiOperation(value = "送验记录详细信息")
    @GetMapping("/getCrystalLog")
    public Result<InspectionRecordDto> getCrystalLog(@ApiParam(value = "长晶棒id") Long longCrystalId) {
        InspectionRecord inspectionRecord = inspectionRecordService.findByLongCrystalId(longCrystalId);
        if (null == inspectionRecord) {
            return ResultGenerator.success();
        }
        return ResultGenerator.success(toEagerDto(inspectionRecord));
    }

    @ApiOperation(value = "确认绑定")
    @PostMapping("/build")
    public Result build(@RequestBody @Valid @ApiParam(value = "送验记录对象") InspectionRecordDto inspectionRecordDto,
            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            inspectionRecordService.build(inspectionRecordDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "呼叫AGV")
    @PostMapping("/callAgv")
    public Result callAgv(@RequestBody @Valid @ApiParam(value = "送验记录对象") InspectionRecordDto inspectionRecordDto,
            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            inspectionRecordService.callAgv(inspectionRecordDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    /**
     * 打开单颗送验按钮：人工送验只有绑一颗能够送验； 关闭单颗送验按钮： 人工必须绑定2颗才可以送验；
     * 关闭和打开按钮对呼叫agv送验没有影响（AGV必须2根才可以送验）;isSingleCrystal是否开单颗送验
     * 
     * @param inspectionRecordDto
     * @param bindingResult
     * @return
     */
    @ApiOperation(value = "只送验不呼叫AGV")
    @PostMapping("/sendCheck")
    public Result sendCheck(@RequestBody @Valid @ApiParam(value = "送验记录对象") InspectionRecordDto inspectionRecordDto,
            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            inspectionRecordService.sendCheck(inspectionRecordDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "计算理论重量")
    @PostMapping("/calcWeight")
    public Result calcWeight(@ApiParam(value = "规格") String specs, @ApiParam(value = "退料长度") Double length) {
        try {
            Double weight = null;
            List<DictionaryItem> items = dictionaryItemService.findByThemeValueAndEnable("WeightRatio", true);// 理论重量系数
            Map<String, DictionaryItem> itemMap = items.stream()
                    .collect(Collectors.toMap(DictionaryItem::getName, dictionaryItem -> dictionaryItem));

            DictionaryItem item = itemMap.get(specs);

            if (item != null) {
                weight = length / Double.valueOf(item.getValue());
                BigDecimal b = new BigDecimal(weight);
                weight = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                return ResultGenerator.success(weight);
            } else {
                return ResultGenerator.success();
            }
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "确认退料")
    @PostMapping("/backWeight")
    public Result backWeight(@RequestBody @Valid @ApiParam(value = "送验退料对象") InspectionBackDto inspectionBackDto,
            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            inspectionRecordService.back(inspectionBackDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "呼叫AGV测试")
    @PostMapping("/callAgvTest")
    public Result callAgvTest(@RequestBody @Valid @ApiParam(value = "送验记录对象") InspectionRecordDto inspectionRecordDto,
            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            String string = inspectionRecordService.callAgvTest(inspectionRecordDto);
            return ResultGenerator.success(string);
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "呼叫AGV")
    @PostMapping("/callBack")
    public Result callBack(@RequestBody @ApiParam(value = "送验记录对象") AgvCallBackParamDto paramDto) {
        try {
            inspectionRecordService.callBack(paramDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "更新送验记录")
    @PostMapping("/update")
    public Result update(@RequestBody @Valid @ApiParam(value = "送验记录") InspectionRecordDto dto,
            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        if (dto.getId() == null) {
            return ResultGenerator.fail("id不能为空");
        }
        InspectionRecord entity = inspectionRecordService.get(dto.getId());
        if (entity == null) {
            return ResultGenerator.fail("原信息不存在");
        }
        try {
            InspectionRecord entityfromFto = fromDto(dto);
            BeanUtils.copyProperties(entityfromFto, entity, BeanUtil.getIgnoreProperties(entityfromFto, null, null));
            inspectionRecordService.saveOrUpdate(entity);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "删除送验记录")
    @PostMapping("/delete")
    public Result remove(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Long[] ids) {
        for (Long id : ids) {
            inspectionRecordService.delete(id);
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "满车绑定完成")
    @PostMapping("/busloadBuild")
    public Result busloadBuild(@RequestBody @Valid @ApiParam(value = "送验记录对象") InspectionRecordDto inspectionRecordDto,
            BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            // 满车绑定接口与呼叫AGV接口的区别--增加了下发mcs
            inspectionRecordService.busloadBuild(inspectionRecordDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }



    @ApiOperation(value = "下发满车绑定信息给MCS")
    @PostMapping("/sendBindingInfo")
    public Result sendBindingInfo(@RequestBody @Valid @ApiParam(value = "送验记录对象") InspectionRecordDto inspectionRecordDto,
                               BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            // 满车绑定接口与呼叫AGV接口的区别--增加了下发mcs
            inspectionRecordService.sendBindingInfo(inspectionRecordDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }


    /**
     * 人工调接口，临时功能，满车绑定下发mcs
     * 用于人工调接口做绑定信息下发mcs，与确认绑定接口下发的区别是，人工绑定下发给mcs的绑定时间是最后一根晶棒的绑定时间，确认绑定接口下发给mcs的绑定时间取的是当前时间
     * @param inspectionRecordDto
     * @param bindingResult
     * @return
     */
    @ApiOperation(value = "人工调接口下发满车绑定信息给MCS")
    @PostMapping("/sendBindingInfoToMcsForManual")
    public Result sendBindingInfoToMcsForManual(@RequestBody @Valid @ApiParam(value = "送验记录对象") InspectionRecordDto inspectionRecordDto,
                                  BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            // 人工调接口，临时功能，满车绑定下发mcs
            inspectionRecordService.sendBindingInfoToMcsRg(inspectionRecordDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "呼叫取晶车")
    @PostMapping("/callTakeCrystalAgv")
    public Result callTakeCrystalAgv(@RequestBody @Valid @ApiParam(value = "呼叫取晶车对象") CallTakeCrystalAgvDto callTakeCrystalAgvDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        try {
            LongCrystal longCrystal = longCrystalService.get(callTakeCrystalAgvDto.getLongCrystalId());
            if(longCrystal == null){
                return ResultGenerator.fail("长晶棒信息不存在！");
            }
            callTakeCrystalAgvDto.setLongCrystal(longCrystal);
            return inspectionRecordService.callTakeCrystalAgv(callTakeCrystalAgvDto);
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }

    @ApiOperation(value = "呼叫取晶车回调")
    @PostMapping("/callTakeCrystalAgvBack")
    public Result callTakeCrystalAgvBack(@RequestBody AgvCallBackParamDto paramDto) {
        try {
            inspectionRecordService.callTakeCrystalAgvBack(paramDto);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
    }


    public InspectionRecordDto toLazyDto(InspectionRecord entity) {
        return modelMapper.map(entity, InspectionRecordDto.class);
    }

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

    public InspectionRecord fromDto(InspectionRecordDto dto) {
        return modelMapper.map(dto, InspectionRecord.class);
    }
}