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

import com.tykj.dev.config.swagger.AutoDocument;
import com.tykj.dev.device.destroy.entity.domain.DeviceDestroyBill;
import com.tykj.dev.device.destroy.entity.enums.DestroyStatus;
import com.tykj.dev.device.destroy.entity.vo.*;
import com.tykj.dev.device.destroy.service.DeviceDestroyBillService;
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.library.subject.vo.FileVo;
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.subject.service.UserPublicService;
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.misc.utils.StringSplitUtil;
import com.tykj.dev.socket.MyWebSocket;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
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 javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.util.*;

/**
 * @author huangxiahao
 */
@RestController
@RequestMapping(value = "/destroy")
@AutoDocument
@Api(tags = "销毁业务模块", value = "销毁业务模块")
public class DeviceDestroyController {

    private final DeviceDestroyBillService deviceDestroyBillService;

    private final TaskService taskService;

    private final DeviceLibraryService deviceLibraryService;

    private final UserPublicService userPublicService;

    private final DeviceLogService deviceLogService;

    private final TaskLogService taskLogService;

    /**
     * 装备销毁对应的生命周期编号
     */
    private static final Integer DEVICE_DESTROY_LIFE_STATUS = 10;

    public DeviceDestroyController(DeviceDestroyBillService deviceDestroyBillServiceyBillService, TaskService taskService, DeviceLibraryService deviceLibraryService, UserPublicService userPublicService, DeviceLogService deviceLogService, TaskLogService taskLogService) {
        this.deviceDestroyBillService = deviceDestroyBillServiceyBillService;
        this.taskService = taskService;
        this.deviceLibraryService = deviceLibraryService;
        this.userPublicService = userPublicService;
        this.deviceLogService = deviceLogService;
        this.taskLogService = taskLogService;
    }

    @Autowired
    MyWebSocket myWebSocket;

    @ApiOperation(value = "查询销毁单", notes = "可以通过这个接口查询销毁单")
    @PostMapping(value = "/summary")
    public ResponseEntity selectRepairBill(@RequestBody DeviceDestroyBillSelectVo deviceDestoryBillSelectVo) {
        return ResultUtil.success(deviceDestroyBillService.getPage(deviceDestoryBillSelectVo, deviceDestoryBillSelectVo.getPageable()));
    }

    @ApiOperation(value = "提交销毁表单", notes = "可以通过这个接口提交销毁表单发起销毁流程")
    @PostMapping(value = "/form")
    @Transactional(rollbackOn = Exception.class)
    public ResponseEntity selectRepairBill(@Validated @RequestBody DeviceDestroyFormVo formVo) {
        //生成销毁账单
        User currentUserInfo = AuthenticationUtils.getAuthentication().getCurrentUserInfo();
        DeviceDestroyBill destroyBill = DeviceDestroyBill.formVoToBill(formVo, currentUserInfo);
        //保存销毁账单
        DeviceDestroyBill deviceDestroyBillEntitySaved = deviceDestroyBillService.addEntity(destroyBill);
        //生成日志所需的文件列表
        ArrayList<FileVo> billList = ListUtil.createList(
                new FileVo("销毁单据", deviceDestroyBillEntitySaved.getFileName(), deviceDestroyBillEntitySaved.getFileUrl())
        );
        //生成装备变更日志
        formVo.getDevices().forEach(d->{
            deviceLogService.addLog(new DeviceLogDto(d,"发起销毁",billList));
            deviceLogService.addLog(new DeviceLogDto(d,"销毁待审核",billList));
        });
        //生成销毁审核任务
        Task task = taskService.start(initTaskBto(deviceDestroyBillEntitySaved));
        //生成任务日志
        taskLogService.addLog(new TaskLogBto(task.getId(),"发起销毁",billList));
        taskLogService.addLog(new TaskLogBto(task.getId(),"销毁待审核",billList));
        myWebSocket.sendMessage1();
        return ResultUtil.success("销毁-出库申请成功");
    }

    @ApiOperation(value = "查询可销毁装备列表", notes = "通过这个接口查询可销毁装备接口")
    @PostMapping(value = "/devices")
    public ResponseEntity selectDevices(@RequestBody CanDestroyDeviceSelectVo canDestoryDeviceSelectVo) {
        DeviceLibrarySelectVo deviceLibrarySelectVo = new DeviceLibrarySelectVo();
        BeanUtils.copyProperties(canDestoryDeviceSelectVo, deviceLibrarySelectVo);
        deviceLibrarySelectVo.setLifeStatus(Arrays.asList(2, 5, 12));
        List<DeviceLibrary> list = deviceLibraryService.getList(deviceLibrarySelectVo);
        return ResultUtil.success(list);
    }

    @ApiOperation(value = "查询销毁单详情", notes = "可以通过这个接口查询销毁单")
    @GetMapping(value = "/detail")
    public ResponseEntity selectDestroyDetail(@Validated @NotNull Integer destroyId) {
        //装备文号
        String docNumber;
        DeviceDestroyDetailResultVo destroyDetailResultVo;
        Set<String> nameSet = new HashSet<>();
        Set<String> modelSet = new HashSet<>();
        List<DeviceLibrary> devices = new ArrayList<>();
        DeviceDestroyBill destroyBill = deviceDestroyBillService.getOne(destroyId);
        //获取销毁详情里的装备
        List<Integer> destroyDetail = StringSplitUtil.split(destroyBill.getDestroyDeviceDetail());
        for (Integer id : destroyDetail) {
            if (id > 0) {
                DeviceLibrary d = deviceLibraryService.getOne(id);
                devices.add(d);
                nameSet.add(d.getName());
                modelSet.add(d.getModel());
            }
        }
        //如果装备已经被销毁则生成拼接文号
        docNumber = makeDocNumber(destroyBill);
        //拼接ResultVo
        destroyDetailResultVo = new DeviceDestroyDetailResultVo(
                destroyBill.getStartUserAId(),
                destroyBill.getStartUserBId(),
                userPublicService.getOne(destroyBill.getStartUserAId()).getName(),
                userPublicService.getOne(destroyBill.getStartUserBId()).getName(),
                destroyBill.getDestroyStatus(),
                destroyBill.getFileName(),
                destroyBill.getFileUrl(),
                docNumber,
                destroyBill.getCreateTime(),
                destroyBill.getUndertaker(),
                destroyBill.getLeader(),
                destroyBill.getSupervisor(),
                StringUtils.join(nameSet, ","),
                StringUtils.join(modelSet, ","),
                userPublicService.findUnitsNameByUserId(destroyBill.getStartUserAId()),
                devices
        );
        return ResultUtil.success(destroyDetailResultVo);
    }

    @ApiOperation(value = "销毁出库单确认", notes = "可以通过这个确认销毁单")
    @PutMapping(value = "/confirmation")
    @Transactional
    public ResponseEntity confirmDestroy(@RequestBody @Validated DeviceDestroyConfirmVo deviceDestoryConfirmVo) throws ParseException {
        //初始化需要的数据
        TaskBto task = taskService.get(deviceDestoryConfirmVo.getTaskId());
        DeviceDestroyBill deviceDestroyBill = deviceDestroyBillService.getOne(task.getBillId());
        //判断审核结果 0为审核通过，1为审核不通过
        if (deviceDestoryConfirmVo.getResult() == 1) {
            //更改账单状态
            deviceDestroyBill.setDestroyStatus(DestroyStatus.CONFIRM_FAILED.getStatus());
            //将任务推进至封存
            taskService.moveToArchive(task);
            taskService.update(task);
        } else {
            //更改账单状态
            deviceDestroyBill.setDestroyStatus(DestroyStatus.CONFIRM_SUCCESS.getStatus());
            //设置销毁时间
            deviceDestroyBill.setDestroyTime(new Date());
            //为账单新增文号
            deviceDestroyBill.setDocNumber(this.deviceDestroyBillService.getNewDocNumber());
            //变更任务状态
            task.setBillStatus(StatusEnum.DESTROY_BUSINESS_CONFIRM_FINISH_SUCCESS.id);
            //将任务推进至完结
            taskService.moveToEnd(task);
            taskService.update(task);
        }
        //生成日志所需的文件列表
        ArrayList<FileVo> billList = ListUtil.createList(
                new FileVo("标签替换单据", deviceDestroyBill.getFileName(), deviceDestroyBill.getFileUrl())
        );
        //更改对应装备的状态为销毁
        handleDeviceDetail(deviceDestroyBill,billList,deviceDestoryConfirmVo.getResult());
        //更新销毁账单
        this.deviceDestroyBillService.updateEntity(deviceDestroyBill);
        //生成任务日志
        taskLogService.addLog(new TaskLogBto(task.getId(),deviceDestoryConfirmVo.getResult() == 0?"销毁成功":"销毁审核失败",billList));
        myWebSocket.sendMessage1();
        return selectDestroyDetail(deviceDestroyBill.getId());
    }

    private void handleDeviceDetail(DeviceDestroyBill deviceDestroyBill,ArrayList<FileVo> billList,Integer flag) {
        List<Integer> list = StringSplitUtil.split(deviceDestroyBill.getDestroyDeviceDetail());
        for (Integer id : list) {
            if (id > 0) {
                if (flag==0){
                    //将装备装备变更为销毁
                    DeviceLibrary deviceLibraryEntity = deviceLibraryService.getOne(id);
                    deviceLibraryEntity.setLifeStatus(DEVICE_DESTROY_LIFE_STATUS);
                    deviceLibraryService.update(deviceLibraryEntity);
                }
                //生成装备日志
                deviceLogService.addLog(new DeviceLogDto(id,flag==0?"装备销毁成功":"装备销毁失败",billList));
            }
        }
    }

    private String makeDocNumber(DeviceDestroyBill deviceDestroyBill) {
        if (deviceDestroyBill.getDestroyTime() != null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(deviceDestroyBill.getDestroyTime());
            int year = calendar.get(Calendar.YEAR);
            return "NO:第" + year + "XH" + deviceDestroyBill.getDocNumber() + "号";
        } else {
            return "";
        }
    }

    private TaskBto initTaskBto(DeviceDestroyBill destroyBill){

        //生成Task
        TaskBto taskBto = new TaskBto(
                StatusEnum.DESTROY_BUSINESS_NEED_CONFIRM.id,
                "标签修改业务",
                0,
                ".",
                destroyBill.getId(),
                BusinessEnum.DESTROY.id,
                destroyBill.getStartUserAId(),
                1,
                "",
                ListUtil.createList(destroyBill.getStartUserAId(), destroyBill.getStartUserBId()));
        return taskBto;
    }

}
