package com.tykj.dev.device.allot.controller;

import com.tykj.dev.config.swagger.AutoDocument;
import com.tykj.dev.device.allot.service.AllotBackBillService;
import com.tykj.dev.device.allot.service.AllotBillService;
import com.tykj.dev.device.allot.subject.domin.AllotBackBill;
import com.tykj.dev.device.allot.subject.domin.AllotBill;
import com.tykj.dev.device.allot.subject.vo.AllotBackBillSaveVo;
import com.tykj.dev.device.allot.subject.vo.AllotBackReceiveVo;
import com.tykj.dev.device.allot.subject.vo.AllotReceiveConfirmVo;
import com.tykj.dev.device.library.service.DeviceLibraryService;
import com.tykj.dev.device.library.service.DeviceLogService;
import com.tykj.dev.device.library.subject.Dto.DeviceLogDto;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.device.library.subject.vo.FileVo;
import com.tykj.dev.device.task.service.TaskService;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.user.read.service.MessageService;
import com.tykj.dev.device.user.read.subject.bto.MessageBto;
import com.tykj.dev.device.user.subject.dao.UserDao;
import com.tykj.dev.device.user.subject.entity.User;
import com.tykj.dev.device.user.subject.service.UserPublicService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.misc.base.ResultObj;
import com.tykj.dev.misc.utils.Snowflake;
import com.tykj.dev.misc.utils.StringSplitUtil;
import com.tykj.dev.rfid.service.InputOutputDeviceService;
import com.tykj.dev.socket.MyWebSocket;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
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.RestController;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author dengdiyi
 */
@RestController
@RequestMapping(value = "/allot")
@AutoDocument
@Api(tags = "装备配发模块", description = "装备配发接口")
@Slf4j
public class AllotBackBillController {

    @Autowired
    private TaskService taskService;

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private AllotBackBillService allotBackBillService;

    @Autowired
    private UserPublicService userPublicService;

    @Autowired
    private DeviceLibraryService deviceLibraryService;

    @Autowired
    private DeviceLogService deviceLogService;

    @Autowired
    private MyWebSocket myWebSocket;

    @Autowired
    private AllotBillService allotBillService;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private InputOutputDeviceService inputOutputDeviceService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private MessageService messageService;

    @ApiOperation(value = "发起配发退回业务", notes = "可以通过这个接口发起配发退回任务")
    @PostMapping(value = "/back")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity allotBack(@RequestBody @Validated AllotBackBillSaveVo allotBackBillSaveVo) {
        //获取当前配发退回task
        TaskBto taskBto = taskService.get(allotBackBillSaveVo.getTaskId());
        //获取父配发业务
        TaskBto fatherTask = taskService.get(taskBto.getParentTaskId());
        //获取配发单
        AllotBill allotBill = allotBillService.getOne(fatherTask.getBillId());
        //更改未勾选装备的状态
        List<Integer> receiveDeviceIds = StringSplitUtil.split(allotBill.getReceiveCheckDetail());
        List<Integer> backDeviceIds = StringSplitUtil.split(allotBackBillSaveVo.getBackCheckDetail());
        receiveDeviceIds.removeAll(backDeviceIds);
        receiveDeviceIds.forEach(integer -> {
            DeviceLibrary deviceLibraryEntity = deviceLibraryService.getOne(integer);
            deviceLibraryEntity.setLifeStatus(2);
            deviceLibraryEntity.setOwnUnit(userUtils.getCurrentUserUnitName());
            deviceLibraryEntity.setManageStatus(1);
            DeviceLogDto deviceLogDto = new DeviceLogDto(integer, "审核成功并入库", null);
            deviceLogService.addLog(deviceLogDto);
            deviceLibraryService.update(deviceLibraryEntity);
        });
        //生成发件单位电子签章id
        Long signId = snowflake.creatNextId();
        Long signId2 = snowflake.creatNextId();
        //存储退回单
        AllotBackBill allotBackBill = allotBackBillSaveVo.toDo();
        allotBackBill.setAllotBillId(taskBto.getBillId());
        allotBackBill.setSendUseraId(userUtils.getCurrentUserId());
        allotBackBill.setLeftSignatureId(signId.toString());
        allotBackBill.setRightSignatureId(signId2.toString());
        AllotBackBill allotBackBill1 = allotBackBillService.addEntity(allotBackBill);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(allotBackBill1.getCreateTime());
        int year = calendar.get(Calendar.YEAR);
        String num = "NO:第" + year + "TH" + allotBackBill1.getId() + "号";
        allotBackBill1.setNum(num);
        //发起子任务
        taskBto.setBillId(allotBackBill1.getId());
        taskBto.setOwnUnit(userPublicService.findUnitIdByName(allotBackBill1.getReceiveUnit()));
        TaskBto taskBto1 = taskService.moveToNext(taskBto, allotBackBill1.getReceiveUseraId());
        //改变装备状态
        List<FileVo> fileVoList = new ArrayList<>();
        if (allotBackBillSaveVo.getFileName() != null && allotBackBillSaveVo.getFileUrl() != null) {
            fileVoList.add(new FileVo("出库确认单", allotBackBillSaveVo.getFileName(), allotBackBillSaveVo.getFileUrl()));
        }
        String[] strings = allotBackBill1.getBackCheckDetail().split("x");
        List<Integer> ids = new ArrayList<>();
        for (String s : strings) {
            //改变出库无误的装备的状态
            if (s.length() >= 2 && "1".equals(s.substring(s.length() - 1))) {
                Integer id = Integer.parseInt(s.substring(0, s.length() - 1));
                ids.add(id);
                DeviceLibrary deviceLibraryEntity = deviceLibraryService.getOne(id);
                deviceLibraryEntity.setLifeStatus(3);
                //记录装备日志
                DeviceLogDto deviceLogDto = new DeviceLogDto(id, "配发退回出库", fileVoList);
                deviceLogService.addLog(deviceLogDto);
                deviceLibraryService.update(deviceLibraryEntity);
            }
        }
        //添加出库白名单
        inputOutputDeviceService.addWhiteDevices(ids,userUtils.getCurrentUnitId(),1);
        log.info("[配发模块]:配发退回出库");
        myWebSocket.sendMessage1();
        return ResponseEntity.ok(new ResultObj<>(taskBto1, signId.toString()));
    }

    @ApiOperation(value = "配发退回接收", notes = "可以通过这个接口配发退回接收")
    @PostMapping(value = "/back/receive")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity allotBackReceive(@RequestBody @Validated AllotBackReceiveVo allotBackReceiveVo) {
        //获取当前任务和账单
        TaskBto taskBto = taskService.get(allotBackReceiveVo.getTaskId());
        taskService.addInvolveUser(taskBto, userUtils.getCurrentUserId());
        AllotBackBill allotBackBill = allotBackBillService.getOne(taskBto.getBillId());
        //更改账单状态
        allotBackBill.setBackStatus(3);
        allotBackBill.setReceiveUseraId(userUtils.getCurrentUserId());
        BeanUtils.copyProperties(allotBackReceiveVo, allotBackBill);
        //任务推至完结
        taskService.moveToEnd(taskBto);
//        taskService.moveToNext(taskBto, allotBackReceiveVo.getReceiveUserbId());
        //分隔装备id信息
        List<FileVo> fileVoList = new ArrayList<>();
        if (allotBackReceiveVo.getBillFileName()!=null&&allotBackReceiveVo.getBillFileUrl()!=null) {
            fileVoList.add(new FileVo("退回单", allotBackReceiveVo.getBillFileName(), allotBackReceiveVo.getBillFileUrl()));
        }
//        fileVoList.add(new FileVo("入库确认单", allotBackReceiveVo.getReceiveFileName(), allotBackReceiveVo.getReceiveFileUrl()));
        String deviceIdDetail = allotBackReceiveVo.getReceiveCheckDetail();
        if (deviceIdDetail != null) {
            String[] strings = deviceIdDetail.split("x");
            for (String s : strings) {
                if (s.length() >= 2) {
                    //接收无误
                    if ("1".equals(s.substring(s.length() - 1))) {
                        Integer id = Integer.parseInt(s.substring(0, s.length() - 1));
                        //改变装备状态
                        DeviceLibrary deviceLibraryEntity = deviceLibraryService.getOne(id);
                        deviceLibraryEntity.setLifeStatus(2);
                        deviceLibraryEntity.setOwnUnit(userUtils.getCurrentUserUnitName());
                        deviceLibraryEntity.setManageStatus(1);
                        deviceLibraryEntity.setLocationUnit(userUtils.getCurrentUserUnitName());
                        //存装备日志
                        DeviceLogDto deviceLogDto = new DeviceLogDto(id, "接收配发退回装备", fileVoList);
                        deviceLogService.addLog(deviceLogDto);
                        deviceLibraryService.update(deviceLibraryEntity);
                    }
                    //接收缺失
                    if ("0".equals(s.substring(s.length() - 1))) {
                        Integer id = Integer.parseInt(s.substring(0, s.length() - 1));
                        //改变装备状态
                        DeviceLibrary deviceLibraryEntity = deviceLibraryService.getOne(id);
                        deviceLibraryEntity.setLifeStatus(11);
                        //存装备日志
                        DeviceLogDto deviceLogDto = new DeviceLogDto(id, "接收配发退回装备丢失", fileVoList);
                        deviceLogService.addLog(deviceLogDto);
                        deviceLibraryService.update(deviceLibraryEntity);
                    }
                }
            }
        }
        //发送阅知信息
        List<Integer> ids = userPublicService.findOtherUser(userUtils.getCurrentUserId());
        ids.addAll(userDao.findAllByUnitsId(userPublicService.findUnitIdByName(allotBackBill.getSendUnit())).stream()
                .map(User::getUserId)
                .collect(Collectors.toList()));
        MessageBto messageBto = new MessageBto(taskBto.getId(),taskBto.getBusinessType(),"接收配发退回装备",ids,1);
        messageService.add(messageBto);
        log.info("[配发模块]:配发退回接收入库");
        myWebSocket.sendMessage1();
        return ResponseEntity.ok("配发退回接收入库");
    }

    @ApiOperation(value = "配发退回接收审核", notes = "可以通过这个接口配发退回接收审核")
    @PostMapping(value = "/back/receive/confirm")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity backReceiveConfirm(@RequestBody @Validated AllotReceiveConfirmVo allotReceiveConfirmVo) {
        //获取当前的账单和任务
        TaskBto taskBto = taskService.get(allotReceiveConfirmVo.getTaskId());
        AllotBackBill allotBackBill = allotBackBillService.getOne(taskBto.getBillId());
        String deviceIdDetail = allotBackBill.getReceiveCheckDetail();
        String[] strings = deviceIdDetail.split("x");
        //审核通过
        if (allotReceiveConfirmVo.getStatus() == 0) {
            //业务完结
            taskService.update(taskService.moveToEnd(taskBto));
            //更新账单
            allotBackBill.setBackStatus(3);
            allotBackBillService.update(allotBackBill);
            for (String s : strings) {
                //改变接收无误的装备的状态
                if (s.length() >= 2 && "1".equals(s.substring(s.length() - 1))) {
                    Integer id = Integer.parseInt(s.substring(0, s.length() - 1));
                    DeviceLibrary deviceLibraryEntity = deviceLibraryService.getOne(id);
                    deviceLibraryEntity.setLifeStatus(2);
                    deviceLibraryEntity.setOwnUnit(userUtils.getCurrentUserUnitName());
                    deviceLibraryEntity.setManageStatus(1);
                    DeviceLogDto deviceLogDto = new DeviceLogDto(id, "审核成功并入库", null);
                    deviceLogService.addLog(deviceLogDto);
                    deviceLibraryService.update(deviceLibraryEntity);
                }
            }
            log.info("[配发模块]:配发退回审核成功并入库");
            myWebSocket.sendMessage1();
            return ResponseEntity.ok("审核成功");
        }
        //审核失败
        if (allotReceiveConfirmVo.getStatus() == 1) {
            //业务封存
            taskService.update(taskService.moveToArchive(taskBto));
            //更新账单状态
            AllotBackBill allotBackBill1 = allotBackBillService.getOne(taskBto.getBillId());
            allotBackBill1.setBackStatus(2);
            allotBackBillService.update(allotBackBill1);
            for (String s : strings) {
                //改变接收无误的装备的状态
                if (s.length() >= 2 && "1".equals(s.substring(s.length() - 1))) {
                    Integer id = Integer.parseInt(s.substring(0, s.length() - 1));
                    DeviceLibrary deviceLibraryEntity = deviceLibraryService.getOne(id);
                    deviceLibraryEntity.setLifeStatus(1);
                    DeviceLogDto deviceLogDto = new DeviceLogDto(id, "配发退回入库审核失败", null);
                    deviceLogService.addLog(deviceLogDto);
                    deviceLibraryService.update(deviceLibraryEntity);
                }
            }
            log.info("[配发模块]:配发退回入库审核失败");
            myWebSocket.sendMessage1();
            return ResponseEntity.ok("配发退回接收入库审核失败");
        } else {
            return ResponseEntity.ok("status只能为0或1");
        }
    }
}
