package xiaoqu.home.open.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import xiaoqu.home.open.aop.AvoidRepeatSubmit;
import xiaoqu.home.open.controller.export.operation.ObjectOperationUnionOutput;
import xiaoqu.home.open.controller.export.operation.ObjectParentOperationUnionOutput;
import xiaoqu.home.open.controller.export.operation.OperationUnionOutput;
import xiaoqu.home.open.controller.export.ToolsExport;
import xiaoqu.home.open.controller.input.operation.OperationInsert;
import xiaoqu.home.open.controller.input.operation.OperationPageInput;
import xiaoqu.home.open.controller.input.plan.PlanOperationInput;
import xiaoqu.home.open.controller.output.operation.OperationOutput;
import xiaoqu.home.open.model.db1.District;
import xiaoqu.home.open.model.db1.User;
import xiaoqu.home.open.model.db2.*;
import xiaoqu.home.open.model.db2.Object;
import xiaoqu.home.open.publicBean.BaseOutput;
import xiaoqu.home.open.publicBean.PageOutput;
import xiaoqu.home.open.service.RedisService4;
import xiaoqu.home.open.service.RedisService5;
import xiaoqu.home.open.service.db1.DistrictService;
import xiaoqu.home.open.service.db2.ObjectService;
import xiaoqu.home.open.service.db2.OperationService;
import xiaoqu.home.open.service.db2.ToolsService;
import xiaoqu.home.open.service.db2.TypeSourceService;
import xiaoqu.home.open.task.bean.DeleteEntityNotice;
import xiaoqu.home.open.task.bean.NameModifyNotice;
import xiaoqu.home.open.utils.DateToConverter;
import xiaoqu.home.open.utils.ResultResponseBeanUtil;
import xiaoqu.home.open.utils.UserUtils;
import xiaoqu.home.open.utils.WrapperUtils;
import xiaoqu.home.open.utils.poi.ExcelUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

@Api(value = "作业相关")
@Controller
@RequestMapping("/operation")
@Slf4j
public class OperationController {
    @Autowired
    DistrictService districtService;
    @Autowired
    RedisService5 redisService5;
    @Autowired
    OperationService operationService;
    @Autowired
    TypeSourceService typeSourceService;

    @Autowired
    RedisService4 redisService4;

    @Autowired
    ToolsService toolsService;
    @Autowired
    ObjectService objectService;


    @ApiOperation(value = "作业分页查询")
    @ResponseBody
    @RequestMapping(value = "/oprationPageList", method = RequestMethod.POST)
    public BaseOutput<PageOutput<OperationOutput>> oprationPageList(HttpServletRequest request, @RequestBody OperationPageInput input) {
        log.info("【oprationPageList】input" + JSONObject.toJSONString(input));
        QueryWrapper<Operation> wrapper = WrapperUtils.getWrapper(false);
        PageOutput<OperationOutput> output = new PageOutput<>();
        if (input.getTreeFlag() != null && input.getTreeFlag() == 1) {
            wrapper.and(wrapperq -> wrapperq.eq("object_name", input.getObjectName()).or().eq("object_parent_name", input.getObjectName()));
            input.setObjectName(null);
        }
        input.setTreeFlag(null);
        WrapperUtils.beanToWrapper(wrapper, input);
        Page<Operation> pageList = new Page<>(input.getPage(), input.getRows());

        List<Operation> list = operationService.page(pageList, wrapper).getRecords();
        List<OperationOutput> outputList = new ArrayList<>();

        QueryWrapper<TypeSource> queryWrapper = WrapperUtils.getWrapper(false);
        queryWrapper.eq("type_name", "operationType");
        queryWrapper.orderByAsc("order_by");
        List<TypeSource> typelist = typeSourceService.list(queryWrapper);
        Map<String, String> maps = typelist.stream().collect(Collectors.toMap(TypeSource::getName, TypeSource::getContent));

        for (Operation operation : list) {
            OperationOutput operationOutput = new OperationOutput();
            BeanUtils.copyProperties(operation, operationOutput);
            if (maps.containsKey(operation.getType().toString())) {
                operationOutput.setTypeString(maps.get(operation.getType().toString()));
            }
            if (operationOutput.getToolNames().length() > 2) {
                operationOutput.setToolsString(operationOutput.getToolNames().substring(1, operationOutput.getToolNames().length() - 1));

            }
            if (operationOutput.getToolIds().length() > 2) {
                operationOutput.setToolIds(operationOutput.getToolIds().substring(1, operationOutput.getToolIds().length() - 1));

            }
            if (operation.getModifyId() == 0) {
                operationOutput.setModifyTime(null);
            }
            if (!operation.getToolIds().equals(",,")) {
                ArrayList<Long> longs = new ArrayList<>();
                String substring = operation.getToolIds().substring(1, operation.getToolIds().length() - 1);
                String[] split = substring.split(",");
                for (int i = 0; i < split.length; i++) {
                    longs.add(Long.parseLong(split[i]));
                }
                operationOutput.setToolIdslist(longs);

            }
            outputList.add(operationOutput);

        }
        output.setPage(pageList.getCurrent());
        output.setRecords(pageList.getTotal());
        output.setTotal(pageList.getPages());
        output.setRows(outputList);

        return ResultResponseBeanUtil.success(output);
    }


    @ApiOperation(value = "增加作业")
    @ResponseBody
    @AvoidRepeatSubmit
    @RequestMapping(value = "/addOperation", method = RequestMethod.POST)
    public BaseOutput<String> addOperation(HttpServletRequest request, @RequestBody OperationInsert input) {
//        User user = UserUtils.getUser(request);
//        log.info("【addOrUpdateObject】User:" +user.getName()+",参数："+ JSONObject.toJSONString(input));

        if (input.getDistrictId() == null || input.getDistrictId() == 0) {
            return ResultResponseBeanUtil.fail("请选择站点");
        }
        if (input.getObjectIds() == null || input.getObjectIds().trim().equals("")) {
            return ResultResponseBeanUtil.fail("请选择对象名称");
        }
        if (input.getType() == null) {
            return ResultResponseBeanUtil.fail("请选择作业分类");
        }
        if (input.getName() == null || input.getName().trim().equals("")) {
            return ResultResponseBeanUtil.fail("请输入作业名称");
        }
        if (input.getStatus() == null) {
            return ResultResponseBeanUtil.fail("请选择停/启用状态");
        }
        District district = districtService.getById(input.getDistrictId());
        QueryWrapper<Object> objectWrapper = WrapperUtils.getWrapper(false);
        String[] objectIds = input.getObjectIds().split(",");

        objectWrapper.in("id", Arrays.asList(objectIds));
        objectWrapper.eq("district_id", input.getDistrictId());
        List<Object> objectlist = objectService.list(objectWrapper);
        if (objectlist == null || objectlist.size() == 0) {
            return ResultResponseBeanUtil.fail("对象不存在，请重新选择");
        }

        QueryWrapper<Operation> checkWrapper = WrapperUtils.getWrapper(false);
        checkWrapper.eq("district_id", input.getDistrictId());
        checkWrapper.in("object_id", Arrays.asList(objectIds));
        checkWrapper.eq("name", input.getName());
        checkWrapper.eq("type", input.getType());

        List<Operation> checklist = operationService.list(checkWrapper);
        if (checklist.size() > 0) {
            StringBuilder stringBuilder = new StringBuilder();
            for (Operation operation : checklist) {
                stringBuilder.append(operation.getObjectName()).append(",");
            }
            return ResultResponseBeanUtil.fail(stringBuilder.toString() + "记录已存在，请修改后提交");

        }

        for (Object object : objectlist) {
            Operation operation = new Operation();
            operation.setAgentId(district.getAgentId());
            String agentName = redisService5.get("name:Agent:" + district.getAgentId());
            String propertyName = redisService5.get("name:Properyt:" + district.getPropertyId());
            operation.setAgentName(agentName);
            operation.setPropertyId(district.getPropertyId());
            operation.setPropertyName(propertyName);
            operation.setDistrictId(district.getId());
            operation.setDistrictName(district.getDistrictName());
            operation.setObjectId(object.getId());
            operation.setObjectName(object.getName());
            operation.setObjectParentId(object.getParentId());
            operation.setObjectParentName(object.getParentName());
            operation.setStatus(input.getStatus());
            operation.setSourceType(0);
            operation.setName(input.getName());
            operation.setStandard(input.getStandard());
            operation.setToolIds("," + (input.getToolIds() == null ? "" : input.getToolIds()) + ",");
            operation.setToolNames("," + (input.getToolNames() == null ? "" : input.getToolNames()) + ",");
            operation.setMethod(input.getMethod());
            operation.setMemo(input.getMemo());
            operation.setType(input.getType());
            operationService.save(operation);
        }
        return ResultResponseBeanUtil.success("添加成功");
    }


    @ApiOperation(value = "修改作业")
    @ResponseBody
    @AvoidRepeatSubmit
    @RequestMapping(value = "/updateOperation", method = RequestMethod.POST)
    public BaseOutput<String> updateOperation(HttpServletRequest request, @RequestBody OperationInsert input) {

        if (input.getId() != null) {
            Operation operation = operationService.getById(input.getId());

            if (operation == null) {
                return ResultResponseBeanUtil.fail("记录不存在,请确认");
            }
            NameModifyNotice nameModifyNotice = null;

            if (!operation.getName().equals(input.getName())) {

                QueryWrapper<Operation> wrapper = WrapperUtils.getWrapper(false);
                wrapper.eq("district_id", operation.getDistrictId());
                wrapper.eq("name", input.getName());
                wrapper.eq("object_id", operation.getObjectId());
                wrapper.eq("type", operation.getType());
                int count = operationService.count(wrapper);
                if (count > 0) {
                    return ResultResponseBeanUtil.fail("记录已存在，请修改后再提交");
                }
                nameModifyNotice = new NameModifyNotice();

                nameModifyNotice.setId(input.getId());
                nameModifyNotice.setLevel(1);
                nameModifyNotice.setNewName(input.getName());
                nameModifyNotice.setOldName(operation.getName());
                nameModifyNotice.setType(4);
                nameModifyNotice.setClassName("Operation");
                // 更新名称
                operation.setName(input.getName());
            }

            if (!operation.getToolIds().equals("," + input.getToolIds() + ",")) {
                operation.setToolIds("," + (input.getToolIds() != null ? input.getToolIds() : "") + ",");
                operation.setToolNames("," + (input.getToolNames() != null ? input.getToolNames() : "") + ",");
            }

            operation.setMemo(input.getMemo() != null ? input.getMemo() : "");
            operation.setStandard(input.getStandard() != null ? input.getStandard() : "");
            operation.setMethod(input.getMethod() != null ? input.getMethod() : "");
            operation.setStatus(input.getStatus());
            operationService.updateById(operation);
            //防止修改失败
            if (nameModifyNotice != null) {
                redisService4.lPush("NameModifyNotice", JSON.toJSONString(nameModifyNotice));
            }


            return ResultResponseBeanUtil.success("修改成功");
        } else {
            return ResultResponseBeanUtil.fail("请选择记录");
        }
    }

    @ApiOperation(value = "删除作业")
    @ResponseBody
    @AvoidRepeatSubmit
    @RequestMapping(value = "/removeOperation", method = RequestMethod.GET)
    public BaseOutput<String> removeOperation(HttpServletRequest request, @RequestParam Long id) {
        Operation operation = operationService.getById(id);
        operation.setSoftDelete(1);
        operationService.updateById(operation);
        DeleteEntityNotice deleteEntityNotice = new DeleteEntityNotice();
        deleteEntityNotice.setId(operation.getId());
        deleteEntityNotice.setLevel(1);
        deleteEntityNotice.setType(4);
        redisService4.lPush("DeleteEntityNotice", JSON.toJSONString(deleteEntityNotice));
        return ResultResponseBeanUtil.success("修改成功");
    }


    @ApiOperation(value = "作业记录导出")
    @PostMapping("/operationExport")
    public void operationExport(HttpServletRequest request, HttpServletResponse response, @RequestBody OperationPageInput input) throws IOException {
        QueryWrapper<Operation> wrapper = WrapperUtils.getWrapper(false);
        User user = UserUtils.getUser(request);
        log.info("【operationExport】user:" + user.getName() + ",参数：" + JSONObject.toJSONString(input));
        if (input.getTreeFlag() != null && input.getTreeFlag() == 1) {
            wrapper.and(wrapperq -> wrapperq.eq("object_name", input.getObjectName()).or().eq("object_parent_name", input.getObjectName()));
            input.setObjectName(null);
        }
        input.setTreeFlag(null);
        wrapper = WrapperUtils.beanToWrapper(wrapper, input);
        List<Operation> operationList = operationService.list(wrapper);
        Map<Long, ObjectParentOperationUnionOutput> objectParentMap = new HashMap<>();
        Map<Long, ObjectOperationUnionOutput> objectMap = new HashMap<>();

        for (Operation operation : operationList) {

            if (objectParentMap.containsKey(operation.getObjectParentId())) {
                ObjectParentOperationUnionOutput objectParentOperationUnionOutput = objectParentMap.get(operation.getObjectParentId());
                if (objectMap.containsKey(operation.getObjectId())) {
                    setSubOperation(operation, objectMap.get(operation.getObjectId()));
                } else {
                    ObjectOperationUnionOutput objectOperationUnionOutput = new ObjectOperationUnionOutput();
                    objectOperationUnionOutput.setObjectId(operation.getObjectId());
                    objectOperationUnionOutput.setObjectName(operation.getObjectName());
                    setSubOperation(operation, objectOperationUnionOutput);
                    objectMap.put(operation.getObjectId(), objectOperationUnionOutput);
                    objectParentOperationUnionOutput.getObjectOperationUnionOutputs().add(objectOperationUnionOutput);
                }

            } else {
                ObjectParentOperationUnionOutput objectParentOperationUnionOutput = new ObjectParentOperationUnionOutput();
                objectParentOperationUnionOutput.setObjectParentId(operation.getObjectParentId());
                objectParentOperationUnionOutput.setObjectParentName(operation.getObjectParentName());
                ObjectOperationUnionOutput objectOperationUnionOutput = new ObjectOperationUnionOutput();
                objectOperationUnionOutput.setObjectId(operation.getObjectId());
                objectOperationUnionOutput.setObjectName(operation.getObjectName());
                setSubOperation(operation, objectOperationUnionOutput);
                objectMap.put(operation.getObjectId(), objectOperationUnionOutput);
                ArrayList<ObjectOperationUnionOutput> objects = new ArrayList<>();
                objects.add(objectOperationUnionOutput);
                objectParentOperationUnionOutput.setObjectOperationUnionOutputs(objects);
                objectParentMap.put(operation.getObjectParentId(), objectParentOperationUnionOutput);
            }
        }
        List<ObjectParentOperationUnionOutput> exportList = new ArrayList<>(objectParentMap.values());

        Map<String, java.lang.Object> map = new HashMap<String, java.lang.Object>();
        String fileTemplate = "./temp/objectOperation.xlsx";
        File fileOut = new File(fileTemplate);
        //从jar里读取文件 然后建立临时文件模板  如果temp 目录已经有了就不读取了
        if (!fileOut.exists()) {
            File dirPath = new File("./temp");
            if (!dirPath.exists()) {
                dirPath.mkdir();
            }
            fileOut.createNewFile();//将模板文件放到临时目录
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/objectOperation.xlsx");
            FileOutputStream fos = new FileOutputStream(fileTemplate);
            byte[] b = new byte[1024];
            while ((inputStream.read(b)) != -1) {
                fos.write(b);// 写入数据
            }
            inputStream.close();
            fos.close();// 保存数据
        }
        TemplateExportParams params = new TemplateExportParams(fileTemplate);
        params.setColForEach(true);
//        log.info("场景导出对象=" + JSON.toJSONString(list));
        map.put("list", exportList);

        Workbook workbook = ExcelExportUtil.exportExcel(params, map);
        String fileName = "对象作业标准化记录" + DateUtil.format(new Date(), "yyyMMddHHmmss") + ".xlsx";
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "iso8859-1"));
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        BufferedOutputStream bufferedOutPut = new BufferedOutputStream(response.getOutputStream());
        workbook.write(bufferedOutPut);
        bufferedOutPut.flush();
        bufferedOutPut.close();
    }

    private void setSubOperation(Operation operation, ObjectOperationUnionOutput objectOperationUnionOutput) {
        switch (operation.getType()) {
            case 0:
                objectOperationUnionOutput.setType0(setOperationUnionOutput(operation));
                break;
            case 1:
                objectOperationUnionOutput.setType1(setOperationUnionOutput(operation));
                break;
            case 2:
                objectOperationUnionOutput.setType2(setOperationUnionOutput(operation));
                break;
            case 3:
                objectOperationUnionOutput.setType3(setOperationUnionOutput(operation));
                break;
            case 4:
                objectOperationUnionOutput.setType4(setOperationUnionOutput(operation));
                break;
        }
    }

    private OperationUnionOutput setOperationUnionOutput(Operation operation) {
        OperationUnionOutput operationUnionOutput = new OperationUnionOutput();
        operationUnionOutput.setMethod(operation.getMethod());
        operationUnionOutput.setName(operation.getName());
        operationUnionOutput.setStandard(operation.getStandard());
        if (operation.getToolNames() != null) {
            operationUnionOutput.setToolNames(operation.getToolNames().substring(1, operation.getToolNames().length() - 1));
        }
        return operationUnionOutput;
    }


    @ApiOperation(value = "计划作业分页查询")
    @ResponseBody
    @RequestMapping(value = "/planoprationPageList", method = RequestMethod.POST)
    public BaseOutput<List<OperationOutput>> planoprationPageList(HttpServletRequest request, @RequestBody PlanOperationInput input) {
        log.info("【planoprationPageList】input" + JSONObject.toJSONString(input));
        QueryWrapper<Operation> wrapper = WrapperUtils.getWrapper(false);
        PageOutput<OperationOutput> output = new PageOutput<>();
        if (input.getTreeFlag() != null && input.getTreeFlag() == 1) {
            wrapper.and(wrapperq -> wrapperq.eq("object_name", input.getObjectName()).or().eq("object_parent_name", input.getObjectName()));
            input.setObjectName(null);
        }
        if (input.getDistrictId() == null) {
            return ResultResponseBeanUtil.fail("请选择所属站点");
        }
        if (input.getObjectIds() != null) {
            wrapper.in("object_id",input.getObjectIds());
            input.setObjectIds(null);
        }
        if (input.getObjectParentIds() != null) {
            wrapper.in("object_parent_id",input.getObjectParentIds());
            input.setObjectParentIds(null);

        }
        input.setTreeFlag(null);
        WrapperUtils.beanToWrapper(wrapper, input);
        Page<Operation> pageList = new Page<>(input.getPage(), input.getRows());
        List<Operation> list = operationService.list(wrapper);
//        List<Operation> list = operationService.page(pageList, wrapper).getRecords();
        List<OperationOutput> outputList = new ArrayList<>();

        QueryWrapper<TypeSource> queryWrapper = WrapperUtils.getWrapper(false);
        queryWrapper.eq("type_name", "operationType");
        queryWrapper.orderByAsc("order_by");
        List<TypeSource> typelist = typeSourceService.list(queryWrapper);
        Map<String, String> maps = typelist.stream().collect(Collectors.toMap(TypeSource::getName, TypeSource::getContent));

        for (Operation operation : list) {
            OperationOutput operationOutput = new OperationOutput();
            BeanUtils.copyProperties(operation, operationOutput);
            if (maps.containsKey(operation.getType().toString())) {
                operationOutput.setTypeString(maps.get(operation.getType().toString()));
            }
            if (operationOutput.getToolNames().length() > 2) {
                operationOutput.setToolsString(operationOutput.getToolNames().substring(1, operationOutput.getToolNames().length() - 1));

            }
            if (operationOutput.getToolIds().length() > 2) {
                operationOutput.setToolIds(operationOutput.getToolIds().substring(1, operationOutput.getToolIds().length() - 1));

            }
            if (operation.getModifyId() == 0) {
                operationOutput.setModifyTime(null);
            }
            if (!operation.getToolIds().equals(",,")) {
                ArrayList<Long> longs = new ArrayList<>();
                String substring = operation.getToolIds().substring(1, operation.getToolIds().length() - 1);
                String[] split = substring.split(",");
                for (int i = 0; i < split.length; i++) {
                    longs.add(Long.parseLong(split[i]));
                }
                operationOutput.setToolIdslist(longs);

            }
            outputList.add(operationOutput);

        }
//        output.setPage(pageList.getCurrent());
//        output.setRecords(pageList.getTotal());
//        output.setTotal(pageList.getPages());
//        output.setRows(outputList);

        return ResultResponseBeanUtil.success(outputList);
    }

}
