package com.ruoyi.project.base.controller;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.ExcelUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.project.base.domain.TBaseDevice;
import com.ruoyi.project.base.domain.TBasePoint;
import com.ruoyi.project.base.mapper.TBaseDeviceMapper;
import com.ruoyi.project.base.mapper.TBasePointMapper;
import com.ruoyi.project.base.service.ITBasePointService;
import com.ruoyi.system.service.ISysDictTypeService;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 密封点Controller
 *
 * @author ruoyi
 * @date 2022-11-11
 */
@RestController
@RequestMapping("/base/point")
public class TBasePointController extends BaseController {
    @Autowired
    private ITBasePointService tBasePointService;
    @Resource
    private TBasePointMapper tBasePointMapper;

    @Autowired
    private ISysDictTypeService isysDictTypeService;

    @Resource
    private TBaseDeviceMapper tBaseDeviceMapper;

    /**
     * 查询密封点列表
     */
    @PreAuthorize("@ss.hasPermi('base:point:list')")
    @GetMapping("/list")
    public TableDataInfo list(TBasePoint tBasePoint) {
        startPage();
        List<TBasePoint> list = tBasePointService.selectTBasePointList(tBasePoint);
        return getDataTable(list);
    }

    @GetMapping("/listByPlan")
    public TableDataInfo listByPlan(TBasePoint tBasePoint) {
        startPage();
        List<TBasePoint> list = tBasePointService.selectTBasePointListByPlan(tBasePoint);
        return getDataTable(list);
    }

    /**
     * 导出密封点列表
     */
    @PreAuthorize("@ss.hasPermi('base:point:export')")
    @Log(title = "密封点导出", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, TBasePoint tBasePoint) {
        List<TBasePoint> list = tBasePointService.selectTBasePointList(tBasePoint);
        ExcelUtil<TBasePoint> util = new ExcelUtil<TBasePoint>(TBasePoint.class);
        util.exportExcel(response, list, "密封点数据");
    }

    /**
     * 获取密封点详细信息
     */
    @PreAuthorize("@ss.hasPermi('base:point:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(tBasePointService.selectTBasePointById(id));
    }

    /**
     * 新增密封点
     */
    @PreAuthorize("@ss.hasPermi('base:point:add')")
    @Log(title = "密封点新增", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TBasePoint tBasePoint) {
        try {
            TBasePoint point = tBasePointService.selectTBasePointByGroupCodeAndExtendCode(tBasePoint);
            if (point == null) {
                tBasePoint.setUpdatedate(new Date());
                tBasePoint.setUpdaterCode(getUserId());
                tBasePoint.setCreaterCode(getUserId());
                return toAjax(tBasePointService.insertTBasePoint(tBasePoint));
            } else {
                return AjaxResult.success("当前装置下的密封点已存在该群组编号和扩展编码!", 0);
            }
        } catch (MyBatisSystemException e) {
            e.printStackTrace();
            return AjaxResult.success("当前装置下的密封点已存在该群组编号和扩展编码!", 0);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error();
        }

    }

    /**
     * 修改密封点
     */
    @PreAuthorize("@ss.hasPermi('base:point:edit')")
    @Log(title = "密封点修改", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody TBasePoint tBasePoint) {
        TBasePoint point = tBasePointService.selectTBasePointByGroupCodeAndExtendCode(tBasePoint);
        if (point == null) {
            tBasePoint.setUpdatedate(new Date());
            tBasePoint.setUpdaterCode(getUserId());
            return toAjax(tBasePointService.updateTBasePoint(tBasePoint));
        } else {
            return AjaxResult.error("当前数据已存在!");
        }
    }

    @PutMapping("/handleApprove")
    @Log(title = "密封点审核", businessType = BusinessType.APPROVE)
    public AjaxResult handleApprove(@RequestBody TBasePoint tBasePoint) {
        tBasePoint.setApproveTime(new Date());
        return toAjax(tBasePointService.updateTBasePointByPointIds(tBasePoint));
    }

    @PutMapping("/handleApproveAll")
    @Log(title = "密封点审核所有", businessType = BusinessType.APPROVE)
    public AjaxResult handleApproveAll(@RequestBody TBasePoint tBasePoint) {
        long status = tBasePoint.getApproveStatus();
        tBasePoint.setApproveStatus(null);
        //查询需要审核数据
        List<TBasePoint> list = tBasePointService.selectTBasePointList(tBasePoint);
        if (list.size() == 0) {
            return AjaxResult.success();
        }
        List<Long> ids = new ArrayList<>();
        for (TBasePoint t : list
        ) {
            ids.add(t.getPointId());
        }
        TBasePoint point = new TBasePoint();
        point.setPointIds(ids.toArray(new Long[ids.size()]));
        point.setApproveTime(new Date());
        point.setApproveStatus(status);
        tBasePointService.updateTBasePointByPointIds(point);
        return AjaxResult.success();
    }

    @PutMapping("/handleUpload")
    @Log(title = "密封点上传文件修改", businessType = BusinessType.UPDATE)
    public AjaxResult handleUpload(@RequestBody TBasePoint tBasePoint) {
        tBasePoint.setUpdaterCode(getUserId());
        if ((tBasePointService.updateTBasePointByUploadFile(tBasePoint) > 0))
            return AjaxResult.success();
        else
            return AjaxResult.error("未找到对应名称的PID图号/组件照片号");
    }

    /**
     * 删除密封点
     */
    @PreAuthorize("@ss.hasPermi('base:point:remove')")
    @Log(title = "密封点删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(tBasePointService.deleteTBasePointByIds(ids));
    }


    @Log(title = "密封点台账导入", businessType = BusinessType.INSERT)
    @PostMapping("/importData")
    public AjaxResult importData(@RequestParam("file") MultipartFile file) throws IOException {
        //获取操作人员ID
        Long userId = getUserId();

        List<SysDictData> mediumTypeDict = isysDictTypeService.selectDictDataByType("medium_type");
        //报错行数统计
        CopyOnWriteArrayList<Integer> failRow = new CopyOnWriteArrayList<>();
        Workbook workbook = ExcelUtils.getWorkBook(file);
        Sheet sheet = workbook.getSheetAt(0);
        List<TBasePoint> list = new ArrayList<>();
        int rowNum = sheet.getPhysicalNumberOfRows();
        //线程池
        ExecutorService executorService = Executors.newFixedThreadPool(30);
        final CountDownLatch latch = new CountDownLatch(rowNum - 1); //相同线程数量的计数
        AtomicInteger successNumber = new AtomicInteger();
        for (int i = 1; i < rowNum; i++) {
            int finalI = i;
            executorService.execute(() -> {
                try {
                    logger.info("读取行数：" + finalI);
                    Row row = sheet.getRow(finalI);
                    int cellNum = row.getLastCellNum();
                    TBasePoint entity = new TBasePoint();
                    for (int j = 0; j < cellNum; j++) {
                        Cell cell = row.getCell(j);
                        if (cell == null) {
                            continue;
                        }
                        String cellValue = ExcelUtils.getCellValue(cell);
                        logger.info("cellValue:" + cellValue);
                        if (j == 0) {
                            //装置名称
                            entity.setPlantName(cellValue);
                        } else if (j == 1) {
                            entity.setPlantCode(cellValue);
                        } else if (j == 3) {
                            //  区域名称
                            entity.setRegionName(cellValue);
                        } else if (j == 4) {
                            entity.setRegionCode(cellValue);
                        } else if (j == 5) {
                            // 平台
                            entity.setLayer(cellValue);
                        } else if (j == 6) {
                            //PID
                            entity.setPidNo(cellValue);
                        } else if (j == 7) {
                            // 设备名称
                            entity.setDevName(cellValue);
                        } else if (j == 8) {
                            // 设备编号
                            entity.setDevCode(cellValue);
                        } else if (j == 9) {
                            // 群组位置
                            entity.setGroupPosition(cellValue);
                        } else if (j == 10) {
                            // 密封点位置
                            entity.setPointPosition(cellValue);
                        } else if (j == 11) {
                            // 群组编码
                            entity.setGroupCode(cellValue);
                        } else if (j == 12) {
                            // 密封点扩展号编码
                            entity.setExtendCode(cellValue);
                        } else if (j == 13) {
                            // 密封点类型
                            entity.setPointType(cellValue);
                        } else if (j == 14) {
                            // 密封点子类型
                            entity.setSubPointType(cellValue);
                        } else if (j == 15) {
                            // 公称直径
                            entity.setDia(cellValue);
                        } else if (j == 16) {
                            // 是否不可达点
                            entity.setUnarrive(cellValue);
                        } else if (j == 17) {
                            // 不可达原因
                            entity.setUnarriveReason(cellValue);
                        } else if (j == 18) {
                            // 是否保温
                            entity.setKeepWarm(cellValue);
                        } else if (j == 19) {
                            // 介质
                            entity.setMedium(cellValue);
                        } else if (j == 20) {
                            for (SysDictData dictData : mediumTypeDict) {
                                if (dictData.getDictLabel().equals(cellValue)) {
                                    // 介质状态
                                    entity.setMediumType(dictData.getDictValue());
                                    break;
                                }
                            }
                        } else if (j == 21) {
                            // toc分数
                            entity.setTocMark(cellValue);
                        } else if (j == 22) {
                            // 甲烷质量分数
                            entity.setMethaneMark(cellValue);
                        } else if (j == 23) {
                            // vocs分数
                            entity.setVocsMark(cellValue);
                        } else if (j == 24) {
                            // 工艺温度
                            entity.setTemperature(cellValue);
                        } else if (j == 25) {
                            // 工艺压力
                            entity.setPressure(cellValue);
                        } else if (j == 26) {
                            // pic图号
                            entity.setPicNo(cellValue);
                        } else if (j == 27) {
                            // 运行时间
                            if (cellValue.length() > 3) {//下次年度检验日期
                                entity.setRunTime(new SimpleDateFormat("yyyy-MM-dd").parse(cellValue));
                            }
                        } else if (j == 28) {
                            // 备注
                            entity.setRemarks(cellValue);
                        }
                    }
                    if (StringUtils.isEmpty(entity.getPointType())) {
                        logger.info("缺少必填项");
                        failRow.add(finalI + 1);
                        throw new InterruptedException(); //中止线程
                    }
                    entity.setCreaterCode(userId);
                    entity.setApproveStatus(0L);
                    TBaseDevice device = tBaseDeviceMapper.selectTBaseDeviceByCode(entity);
                    if (device == null) {
                        logger.info("没有设备数据");
                        failRow.add(finalI + 1);
                        throw new InterruptedException(); //中止线程
                    } else {
                        entity.setDevId(device.getDevId());
                        entity.setPlantId(device.getPlantId());
                        entity.setRegionId(device.getRegionId());
                        logger.info("entity:" + entity);
                        //进行数据更新
                        entity.setUpdatedate(new Date());
                        entity.setUpdaterCode(userId);
                        tBasePointMapper.insertTBasePoint(entity);
                        successNumber.getAndIncrement();
                    }
                } catch (InterruptedException e) {
                    logger.info("中止线程" + Thread.currentThread().getName());
                } catch (DuplicateKeyException e) {
                    logger.info("重复数据");
                    failRow.add(finalI + 1);
                } catch (Exception e) {
                    failRow.add(finalI + 1);
                    e.printStackTrace();
                } finally {
                    latch.countDown(); //线程计数
                }
            });
        }
        try {
            latch.await(); //线程计数完毕后继续执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService.shutdown();

        logger.info("list:" + JSON.toJSONString(list));
        logger.info("successNumber:" + successNumber);
        logger.info("failNumber:" + failRow.size());
        logger.info("failRow:" + failRow);
        return AjaxResult.success(String.valueOf(successNumber.get()), failRow);
    }

    @Log(title = "密封点文件上传", businessType = BusinessType.UPDATE)
    @PostMapping("/uploadFile")
    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
        if (!file.isEmpty()) {
            String avatar = FileUploadUtils.upload(RuoYiConfig.getFilePath("/point"), file);
            return AjaxResult.success(avatar);
        }
        return AjaxResult.error("上传异常，请联系管理员");
    }


}
