package com.njcn.gather.icd.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gather.icd.mapper.PqIcdPathMapper;
import com.njcn.gather.icd.pojo.enums.IcdResponseEnum;
import com.njcn.gather.icd.pojo.param.PqIcdPathParam;
import com.njcn.gather.icd.pojo.po.PqIcdPath;
import com.njcn.gather.icd.service.IPqIcdPathService;
import com.njcn.gather.pojo.enums.DetectionResponseEnum;
import com.njcn.gather.report.pojo.enums.ReportResponseEnum;
import com.njcn.web.factory.PageFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

/**
 * @author caozehui
 * @date 2025-02-10
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PqIcdPathServiceImpl extends ServiceImpl<PqIcdPathMapper, PqIcdPath> implements IPqIcdPathService {

    @Override
    public List<PqIcdPath> listAll() {
        return this.lambdaQuery().eq(PqIcdPath::getState, DataStateEnum.ENABLE.getCode()).list();
    }

    @Override
    public Page<PqIcdPath> listIcd(PqIcdPathParam.QueryParam param) {
        LambdaQueryWrapper<PqIcdPath> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PqIcdPath::getState, DataStateEnum.ENABLE.getCode())
                .like(StrUtil.isNotBlank(param.getName()), PqIcdPath::getName, param.getName())
                .orderByDesc(PqIcdPath::getCreateTime);
        Page<PqIcdPath> page = this.page(new Page<>(PageFactory.getPageNum(param), PageFactory.getPageSize(param)), wrapper);
        String commInstallPath = this.getCommInstallPath();
        page.getRecords().forEach(pqIcdPath -> {
            PqIcdPath.FileVO fileVO = new PqIcdPath.FileVO();
            fileVO.setUrl(commInstallPath + "\\DeviceControl\\Config\\" + pqIcdPath.getName() + ".txt");
            fileVO.setName(pqIcdPath.getName() + ".txt");
            pqIcdPath.setMappingFile(fileVO);
        });
        return page;
    }

    @Override
    @Transactional
    public boolean addIcd(PqIcdPathParam param) {
        param.setName(param.getName().trim());
        this.checkRepeat(param, false);
        PqIcdPath pqIcdPath = new PqIcdPath();
        BeanUtils.copyProperties(param, pqIcdPath);
        pqIcdPath.setState(DataStateEnum.ENABLE.getCode());

        String commInstallPath = this.getCommInstallPath();
        System.out.println("commInstallPath = " + commInstallPath);
        long FILE_SIZE_LIMIT = 1 * 1024 * 1024;
        MultipartFile mappingFile = param.getMappingFile();

        System.out.println("mappingFile = " + ObjectUtil.isNotNull(mappingFile) + " " + !mappingFile.isEmpty());
        if (ObjectUtil.isNotNull(mappingFile) && !mappingFile.isEmpty()) {
            String mappingFilename = mappingFile.getOriginalFilename();

            if (!mappingFilename.endsWith(".txt")) {
                throw new BusinessException(IcdResponseEnum.FILE_TYPE_ERROR);
            }
            if (mappingFile.getSize() > FILE_SIZE_LIMIT) {
                throw new BusinessException(IcdResponseEnum.FILE_SIZE_ERROR);
            }

            try {
                // 如果文件存在，则先删除
                String mappingFilePath = commInstallPath + "\\DeviceControl\\Config\\" + mappingFilename;
                System.out.println("mappingFilePath = " + mappingFilePath);
                Path path = Paths.get(mappingFilePath);
                File file = path.toFile();
                if (file.exists()) {
                    file.delete();
                }

                // 保存文件
                byte[] bytes = mappingFile.getBytes();
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(mappingFilePath));
                bufferedOutputStream.write(bytes);
                bufferedOutputStream.flush();

                bufferedOutputStream.close();
                System.out.println("File saved successfully");
            } catch (IOException e) {
                throw new BusinessException(ReportResponseEnum.FILE_UPLOAD_FAILED);
            }
        } else {
            System.out.println("mappingFile is null or empty");
            throw new BusinessException(IcdResponseEnum.FILE_NOT_NULL);
        }

        this.executeRestartCmd(commInstallPath);

        return this.save(pqIcdPath);
    }

    /**
     * 执行重启通讯服务脚本
     *
     * @param commInstallPath
     */
    private void executeRestartCmd(String commInstallPath) {
        // 以管理员身份运行bat脚本
        String batFilePath = commInstallPath + "\\重启所有服务.bat";
        try {
            Runtime.getRuntime().exec(batFilePath);
        } catch (IOException e) {
            log.error("重启通讯服务失败", e);
        }
    }

    private String getCommInstallPath() {
        String workDir = System.getProperty("user.dir");
//        String workDir = "D:\\program\\CN_Gather";
        // 获取映射文件存放文件夹
        String dirPath = workDir + "\\9100";
        int index = workDir.indexOf("\\resources\\extraResources\\java");
        if (index != -1) {
            dirPath = workDir.substring(0, workDir.indexOf("\\resources\\extraResources\\java")) + "\\9100";
        }
        return dirPath;
    }

    @Override
    @Transactional
    public boolean updateIcd(PqIcdPathParam.UpdateParam param) {
        param.setName(param.getName().trim());
        this.checkRepeat(param, true);
        PqIcdPath pqIcdPath = new PqIcdPath();
        BeanUtils.copyProperties(param, pqIcdPath);

        String commInstallPath = this.getCommInstallPath();
        long FILE_SIZE_LIMIT = 1 * 1024 * 1024;
        MultipartFile mappingFile = param.getMappingFile();
        if (ObjectUtil.isNotNull(mappingFile) && !mappingFile.isEmpty()) {
            String mappingFilename = mappingFile.getOriginalFilename();

            if (!mappingFilename.endsWith(".txt")) {
                throw new BusinessException(IcdResponseEnum.FILE_TYPE_ERROR);
            }
            if (mappingFile.getSize() > FILE_SIZE_LIMIT) {
                throw new BusinessException(IcdResponseEnum.FILE_SIZE_ERROR);
            }

            try {
                // 如果文件存在，则先删除
                String mappingFilePath = commInstallPath + "\\DeviceControl\\Config\\" + mappingFilename;
                Path path = Paths.get(mappingFilePath);
                File file = path.toFile();
                if (file.exists()) {
                    file.delete();
                }

                // 保存文件
                byte[] bytes = mappingFile.getBytes();
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(mappingFilePath));
                bufferedOutputStream.write(bytes);
                bufferedOutputStream.flush();

                bufferedOutputStream.close();
            } catch (IOException e) {
                throw new BusinessException(ReportResponseEnum.FILE_UPLOAD_FAILED);
            }
        }

        this.executeRestartCmd(commInstallPath);

        return this.updateById(pqIcdPath);
    }

    @Override
    @Transactional
    public boolean deleteIcd(List<String> ids) {
        List<PqIcdPath> pqIcdPaths = this.listByIds(ids);
        String commInstallPath = this.getCommInstallPath();
        pqIcdPaths.forEach(pqIcdPath -> {
            String mappingFilePath = commInstallPath + "\\DeviceControl\\Config\\" + pqIcdPath.getName() + ".txt";
            Path path = Paths.get(mappingFilePath);
            File file = path.toFile();
            if (file.exists()) {
                file.delete();
            }
        });

        return this.lambdaUpdate().in(PqIcdPath::getId, ids).set(PqIcdPath::getState, DataStateEnum.DELETED.getCode()).update();
    }

    @Override
    public PqIcdPath getIcdByDevType(String devTypeId) {
        return this.baseMapper.selectIcdByDevType(devTypeId);
    }

    private void checkRepeat(PqIcdPathParam param, boolean isExcludeSelf) {
        LambdaQueryWrapper<PqIcdPath> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PqIcdPath::getName, param.getName())
                .eq(PqIcdPath::getState, DataStateEnum.ENABLE.getCode());
        if (isExcludeSelf) {
            if (param instanceof PqIcdPathParam.UpdateParam) {
                wrapper.ne(PqIcdPath::getId, ((PqIcdPathParam.UpdateParam) param).getId());
            }
        }
        int count = this.count(wrapper);
        if (count > 0) {
            throw new BusinessException(DetectionResponseEnum.ICD_PATH_NAME_REPEAT);
        }
    }
}
