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

import com.tykj.dev.config.swagger.AutoDocument;
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.DeviceLibrarySelectVo;
import com.tykj.dev.device.packing.service.PackingLibraryService;
import com.tykj.dev.device.packing.subject.domin.PackingLibrary;
import com.tykj.dev.device.packing.subject.vo.PackingLibrarySelectVo;
import com.tykj.dev.device.retired.entity.domain.DeviceRetiredBill;
import com.tykj.dev.device.retired.entity.enums.RetiredStatus;
import com.tykj.dev.device.retired.entity.vo.*;
import com.tykj.dev.device.retired.service.DeviceRetiredBillService;
import com.tykj.dev.device.task.service.TaskLogService;
import com.tykj.dev.device.task.service.TaskService;
import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.bto.TaskLogBto;
import com.tykj.dev.device.task.subject.common.BusinessEnum;
import com.tykj.dev.device.task.subject.common.StatusEnum;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.user.subject.entity.User;
import com.tykj.dev.device.user.util.AuthenticationUtils;
import com.tykj.dev.misc.utils.ListUtil;
import com.tykj.dev.misc.utils.ResultUtil;
import com.tykj.dev.socket.MyWebSocket;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.transaction.Transactional;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author HuangXiahao
 * @version V1.0
 **/
@RestController
@RequestMapping(value = "/retired")
@AutoDocument
@Api(tags = "退装业务模块", value = "退装业务模块")
public class DeviceRetiredController {

    private final DeviceRetiredBillService deviceRetiredBillService;

    private final TaskService taskService;

    private final PackingLibraryService packingLibraryService;

    private final DeviceLibraryService deviceLibraryService;

    private final DeviceLogService deviceLogService;

    private final TaskLogService taskLogService;

    @Autowired
    private AuthenticationUtils AuthenticationUtils;

    public DeviceRetiredController(DeviceRetiredBillService deviceRetiredBillService, TaskService taskService, PackingLibraryService packingLibraryService, DeviceLibraryService deviceLibraryService, DeviceLogService deviceLogService, TaskLogService taskLogService) {
        this.deviceRetiredBillService = deviceRetiredBillService;
        this.taskService = taskService;
        this.packingLibraryService = packingLibraryService;
        this.deviceLibraryService = deviceLibraryService;
        this.deviceLogService = deviceLogService;
        this.taskLogService = taskLogService;
    }

    @Autowired
    MyWebSocket myWebSocket;

    @ApiOperation(value = "查询可退装装备", notes = "可以通过这个接口查询销毁单")
    @PostMapping(value = "/devices")
    public ResponseEntity selectRepairBill(@RequestBody CanRetiredDeviceSelectVo canRetiredDeviceSelectVo) {
        //最终返回的List<VO>
        List<DeviceRetiredResultVo> deviceRetiredResultVos = new ArrayList<>();
        //查询类构建
        PackingLibrarySelectVo packingLibrarySelectVo = new PackingLibrarySelectVo();
        BeanUtils.copyProperties(canRetiredDeviceSelectVo, packingLibrarySelectVo);
        List<PackingLibrary> list = packingLibraryService.getList(packingLibrarySelectVo);
        //循环获取列装主体的数量，并生成VO
        list.forEach(packingLibrary -> {
            DeviceRetiredResultVo deviceRetiredResultVo = calcDeviceRetiredResultVo(packingLibrary);
            deviceRetiredResultVos.add(deviceRetiredResultVo);
        });
        return ResultUtil.success(deviceRetiredResultVos);
    }

    @ApiOperation(value = "提交退装表单", notes = "可以通过这个接口提交销毁表单发起退装流程")
    @PostMapping(value = "/form")
    @Transactional(rollbackOn = Exception.class)
    public ResponseEntity selectRepairBill(@Validated @RequestBody DeviceRetiredFormVo formVo) {
        //生成销毁账单
        User currentUserInfo = Objects.requireNonNull(AuthenticationUtils.getAuthentication()).getCurrentUserInfo();
        DeviceRetiredBill retiredBill = DeviceRetiredBill.formVoToBill(formVo, currentUserInfo);
        retiredBill = deviceRetiredBillService.addEntity(retiredBill);
        //生成Task
        Task task = taskService.start(initTaskBto(retiredBill));
        //生成任务日志
        taskLogService.addLog(new TaskLogBto(task.getId(), "发起退装", null));
        taskLogService.addLog(new TaskLogBto(task.getId(), "退装待审核", null));
        myWebSocket.sendMessage1();
        return ResultUtil.success("退装申请成功");
    }

    @ApiOperation(value = "查询退装单详情", notes = "可以通过这个接口查询退装单")
    @GetMapping(value = "/detail")
    public ResponseEntity selectDestoryDetail(Integer retiredId) {
        DeviceRetiredDetailResultVo deviceRetiredDetailResultVo = new DeviceRetiredDetailResultVo();
        DeviceRetiredBill deviceRetiredBillEntity = deviceRetiredBillService.getOne(retiredId);
        //获取销毁详情里的装备
        String[] deviceDetails = getRetiredDeviceList(deviceRetiredBillEntity.getRetiredDetail());
        for (String deviceDetail : deviceDetails) {
            Integer deviceId = Integer.valueOf(deviceDetail.substring(0, deviceDetail.length() - 1));
            deviceRetiredDetailResultVo.getPackingLibrarys().add(packingLibraryService.getOne(deviceId));
        }
        deviceRetiredDetailResultVo.setRetiredStatus(deviceRetiredBillEntity.getRetiredStatus());
        deviceRetiredDetailResultVo.setConfirmUserId(deviceRetiredBillEntity.getUserBId());
        deviceRetiredDetailResultVo.setStartUserId(deviceRetiredBillEntity.getUserAId());
        return ResultUtil.success(deviceRetiredDetailResultVo);
    }

    @ApiOperation(value = "退装出库单审核", notes = "可以通过这个审核退装单")
    @PutMapping(value = "/confirmation")
    @Transactional
    public ResponseEntity confirmDestroy(@RequestBody @Validated DeviceRetiredConfirmVo deviceRetiredConfirmVo) {
        //初始化需要的数据
        TaskBto task = taskService.get(deviceRetiredConfirmVo.getTaskId());
        DeviceRetiredBill deviceRetiredBillEntity = deviceRetiredBillService.getOne(task.getBillId());
        //判断审核结果
        if (deviceRetiredConfirmVo.getResult() == 1) {
            //更改账单状态
            deviceRetiredBillEntity.setRetiredStatus(RetiredStatus.CONFIRM_FAILED.getStatus());
            //将任务推进至封存
            taskService.moveToArchive(task);
            taskService.update(task);
        }else {
            //更改账单状态
            deviceRetiredBillEntity.setRetiredStatus(RetiredStatus.CONFIRM_SUCCESS.getStatus());
            //将任务推进至完结
            taskService.moveToEnd(task);
            taskService.update(task);
            //更改对应列装库的状态为退装
            String[] deviceRetiredArrays = getRetiredDeviceList(deviceRetiredBillEntity.getRetiredDetail());
            for (String deviceDetail : deviceRetiredArrays) {
                Integer deviceId = Integer.valueOf(deviceDetail.substring(0, deviceDetail.length() - 1));
                PackingLibrary packingLibraryServiceOne = packingLibraryService.getOne(deviceId);
                packingLibraryServiceOne.setPackingStatus(3);
                packingLibraryServiceOne.setExitTime(Timestamp.from(new Date().toInstant()));
                packingLibraryService.update(packingLibraryServiceOne);
                //更改对应的装备为退装
                changeDeviceToRetired(packingLibraryServiceOne.getId());
            }
        }
        //生成日志
        taskLogService.addLog(new TaskLogBto(task.getId(),deviceRetiredConfirmVo.getResult()==0?"退装审核失败":"退装审核成功",null));
        myWebSocket.sendMessage1();
        return selectDestoryDetail(deviceRetiredBillEntity.getId());
    }


    private String[] getRetiredDeviceList(String destoryDeviceDetail) {
        destoryDeviceDetail = destoryDeviceDetail.substring(1);
        return destoryDeviceDetail.split("x");
    }

    private DeviceRetiredResultVo calcDeviceRetiredResultVo(PackingLibrary packingLibraryEntity) {
        DeviceRetiredResultVo deviceRetiredResultVo = new DeviceRetiredResultVo();
        BeanUtils.copyProperties(packingLibraryEntity, deviceRetiredResultVo);
        deviceRetiredResultVo.setCount(deviceRetiredBillService.getCantPackingCount(packingLibraryEntity.getId()));
        List<PackingLibrary> PackingChildren = packingLibraryEntity.getChilds();
        for (PackingLibrary p : PackingChildren) {
            DeviceRetiredResultVo childDeviceRetiredResultVo = new DeviceRetiredResultVo();
            BeanUtils.copyProperties(p, childDeviceRetiredResultVo);
            childDeviceRetiredResultVo.setCount(deviceRetiredBillService.getCantPackingCount(p.getId()));
            deviceRetiredResultVo.getChildNodes().add(childDeviceRetiredResultVo);
        }
        return deviceRetiredResultVo;
    }

    /**
     * 将该列装下的所有装备生命周期都变更为退装
     * @param packingId
     */
    public void changeDeviceToRetired(Integer packingId){
        //生成装备查询VO
        DeviceLibrarySelectVo deviceLibrarySelectVo = new DeviceLibrarySelectVo();
        deviceLibrarySelectVo.setPackingId(packingId);
        //查询
        List<DeviceLibrary> list = deviceLibraryService.getList(deviceLibrarySelectVo);
        //遍历查询出来的list 将list中的每一件装备的状态都设置为退装
        list.forEach(d->{
            d.setLifeStatus(8);
            deviceLibraryService.addEntity(d);
            deviceLogService.addLog(new DeviceLogDto(d.getId(),"装备退装",null));
            //包括装备的配件也设置为退装
            List<DeviceLibrary> deviceChildren = d.getChilds();
            for (DeviceLibrary childDevice : deviceChildren) {
                childDevice.setLifeStatus(8);
                deviceLibraryService.addEntity(childDevice);
                deviceLogService.addLog(new DeviceLogDto(childDevice.getId(),"装备退装",null));
            }
        });
    }

    private TaskBto initTaskBto(DeviceRetiredBill retiredBill){
        //生成Task
        TaskBto taskBto = new TaskBto(
                StatusEnum.RETIRED_BUSINESS_NEED_CONFIRM.id,
                "退装业务",
                0,
                ".",
                retiredBill.getId(),
                BusinessEnum.RETIRED.id,
                retiredBill.getUserAId(),
                1,
                "",
                ListUtil.createList(retiredBill.getUserAId(), retiredBill.getUserBId()));
        return taskBto;
    }

}
