package com.pqs9900.serviceImpl.filebackup;

import com.njcn.mapper.log.UserLogMapper;
import com.njcn.pojo.log.UserLog;
import com.njcn.utils.AppConfig;
import com.njcn.utils.ThreeDes;
import com.pqs9900.mapper.filebackup.FileBackUpMapper;
import com.pqs9900.pojo.filebackup.FileBackUp;
import com.pqs9900.service.filebackup.FileBackUpService;
import org.apache.ibatis.io.Resources;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;

/**
 * @author xuyang
 * @date 2020/9/11 16:46
 */
@Service
public class FileBackUpServiceImpl implements FileBackUpService {

    private static final Logger logger = LoggerFactory.getLogger(FileBackUpServiceImpl.class);

    private XSSFWorkbook xssfWorkbook;

    @Resource
    private FileBackUpMapper fileBackUpMapper;

    @Resource
    private AppConfig appConfig;

    @Resource
    UserLogMapper logMapper;

    @Override
    public Map<String, Object> fileCode() {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        Date date = new Date();
        SimpleDateFormat sqlFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<FileBackUp> fileBackUpList = fileBackUpMapper.getFileList();
        if (fileBackUpList.size() == 0) {
            resultMap.put("code", -1);
            return resultMap;
        } else {
            String filePath = appConfig.getTmppath() + File.separator + "backup.txt";
            File file = new File(filePath);
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    logger.error("异常是" + e.toString());
                }
            }
            //创建FileWriter对象
            FileWriter writer = null;
            try {
                writer = new FileWriter(file);
                //向文件中写入内容
                for (int i = 0; i < fileBackUpList.size(); i++) {
                    String sqlString = sqlFormat.format(fileBackUpList.get(i).getUpdateTime()) + "|" + fileBackUpList.get(i).getUserLogIndex() + "|insert into pqs_userlog (USERLOG_INDEX, USER_INDEX, USERLOG_DESCRIBE, TYPE, UPDATETIME, IP, SYSTYPE, STATE, RESULT) values ('" + fileBackUpList.get(i).getUserLogIndex() + "', '" + fileBackUpList.get(i).getUserIndex() + "', '" + fileBackUpList.get(i).getUserLogDescribe() + "', '" + fileBackUpList.get(i).getType() + "', to_date('" + sqlFormat.format(fileBackUpList.get(i).getUpdateTime()) + "', 'yyyy-mm-dd hh24:mi:ss'), '" + fileBackUpList.get(i).getIp() + "', '" + fileBackUpList.get(i).getSystem() + "', " + fileBackUpList.get(i).getNumber() + ", '" + fileBackUpList.get(i).getResult() + "');" + "\r\n";
                    String kongge = "\r\n";
                    writer.write(sqlString + kongge);
                }
                writer.flush();
                resultMap.put("code", 0);
                resultMap.put("filePath", filePath);
            } catch (IOException e) {
                logger.error("写文件流异常，异常为" + e.toString());
            } finally {
                if (null != writer) {
                    try {
                        writer.close();
                    } catch (IOException e) {
                        logger.error("关闭流异常，异常为" + e.toString());
                    }
                }
            }
            return resultMap;
        }
    }

    @Override
    public Integer deleteUserLog() {
//        return fileBackUpMapper.deleteUserlog();
        return 1;
    }

    @Override
    public Map<String, Object> fileRecovery() {
        Map<String, Object> map = new HashMap<>();
        List<String> sqlList = fileSql();
        return readUserLog(sqlList);
    }

    //执行文件中的sql语句
    private Map<String, Object> readUserLog(List<String> sqlList) {
        Map<String, Object> map = new HashMap<>();
        if (sqlList.size() > 0) {
            //初始化Connection
            Connection con = null;
            PreparedStatement pstm = null;
            ResultSet rs = null;
            String sql = null;
            //配置参数
            try {
                Properties props = Resources.getResourceAsProperties("jdbc.properties");
                String url = props.getProperty("oracle.jdbcUrl");
                String driverClassName = props.getProperty("oracle.driverClass");
                props.setProperty("userName", ThreeDes.decryptThreeDes(props.getProperty("oracle.user")));
                props.setProperty("password", ThreeDes.decryptThreeDes(props.getProperty("oracle.password")));
                String username = props.getProperty("userName");
                String password = props.getProperty("password");
                //加载驱动程序
                Class.forName(driverClassName);
                con = DriverManager.getConnection(url, username, password);

                /**
                 * 原先每执行一次创建一次连接
                 */
                int count = 0;
                for (int i = 0; i < sqlList.size(); i++) {
                    sql = sqlList.get(i);
                    int findex = sql.indexOf('|');
                    int lindex = sql.lastIndexOf("|");
                    String time = sql.substring(0, findex);

                    String logIndex = sql.substring(findex + 1, lindex);
                    //判断当前索引是否已经存在库里，存在则跳出，否则插入
                    UserLog userLog = new UserLog();
                    userLog.setUserLogIndex(logIndex);
                    userLog = logMapper.selectOne(userLog);
                    if (userLog == null) {
                        String excSql = sql.substring(lindex + 1);
                        //先判断时间是否为6个月之前的
                        if (judgeTime(time, excSql)) {
                            continue;
                        }
//                        excSql= StringEscapeUtils.escapeSql(excSql);
                        pstm = con.prepareStatement(excSql);
                        rs = pstm.executeQuery();
                        pstm.close();
                        count++;
                    }
                }
                /**
                 * 结束
                 */
                map.put("code", 200);
                map.put("total", count);
            } catch (Exception e) {
                logger.error("异常是" + e.toString());
            } finally {
                if (rs != null) {
                    try {
                        rs.close();
                    } catch (SQLException e) {
                        logger.error("异常是" + e.toString());
                    }
                }
                // 关闭执行通道
                if (pstm != null) {
                    try {
                        pstm.close();
                    } catch (SQLException e) {
                        logger.error("异常是" + e.toString());
                    }
                }
                // 关闭连接通道
                try {
                    if (con != null && (!con.isClosed())) {
                        con.close();
                    }
                } catch (SQLException e) {
                    logger.error("异常是" + e.toString());
                }
            }
        } else {
            map.put("code", 500);
        }
        return map;
    }

    private boolean judgeTime(String time, String sql) throws ParseException {
        boolean flag = false;
        int index = sql.indexOf("在");
        if (index > -1) {
            String operateTime = sql.substring(index + 1, index + 17);
            if (!time.substring(0, 16).equalsIgnoreCase(operateTime)) {
                return true;
            }
        }
        SimpleDateFormat sqlFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = sqlFormat.parse(time);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 6);
        Calendar now = Calendar.getInstance();
        if (calendar.before(now)) {
            flag = true;
        }

        return flag;
    }

    //读取文件备份的sql语句
    public List<String> fileSql() {
        BufferedReader in = null;
        String filePath = appConfig.getTmppath() + File.separator + "backup.txt";
        List<String> sqlList = new ArrayList<>();
        File file = new File(filePath);
        try {
            in = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            String line ;
            while ((line = in.readLine()) != null) {
                if (!"".equals(line)) {
                    sqlList.add(line);
                }
            }
        } catch (FileNotFoundException e) {
            logger.error("异常是" + e.toString());
        } catch (IOException e) {
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("输入流关闭异常，异常为：" + e.toString());
                }
            }
        }
        if (null == sqlList || 0 == sqlList.size()) {
            return null;
        } else {
            List<String> sqlListAfterDispose = new ArrayList<>();
            for (String s : sqlList) {
                //去掉每条sql后面可能带有的“；”
                String replaceString = s.trim().replace(";", "");
                //判断sql是否是影响数据库结构或者删除数据
                sqlListAfterDispose.add(replaceString);
            }
            return sqlListAfterDispose;
        }
    }


    //关闭prepareStatement
    public static void close(PreparedStatement statement) {
        try {
            if (statement != null || !statement.isClosed()) {
                statement.close();
            }
        } catch (SQLException e) {
            logger.error("异常是" + e.toString());
        }
    }

    //将查询到的数据写入excel文档中
    private void generateExcel(List<FileBackUp> list, HttpServletResponse response, HttpServletRequest request) {
        xssfWorkbook = new XSSFWorkbook();
        XSSFSheet xssfSheet = xssfWorkbook.createSheet("sheet");
        String fileName = "审计备份";
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        XSSFRow row = xssfSheet.createRow(0);
        XSSFCell cell = null;
        InputStream is = null;
        SimpleDateFormat sqlFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //设置单元格大小
        xssfSheet.setColumnWidth(0, 4000);
        xssfSheet.setColumnWidth(1, 4000);
        xssfSheet.setColumnWidth(2, 6000);
        xssfSheet.setColumnWidth(3, 4000);
        xssfSheet.setColumnWidth(4, 4000);
        xssfSheet.setColumnWidth(5, 2000);
        xssfSheet.setColumnWidth(6, 1000);
        xssfSheet.setColumnWidth(7, 1000);
        xssfSheet.setColumnWidth(8, 1000);

        //表头
        cell = row.createCell(0);
        cell.setCellValue("userLogIndex");

        cell = row.createCell(1);
        cell.setCellValue("userIndex");

        cell = row.createCell(2);
        cell.setCellValue("userLogDescribe");

        cell = row.createCell(3);
        cell.setCellValue("type");

        cell = row.createCell(4);
        cell.setCellValue("updateTime");

        cell = row.createCell(5);
        cell.setCellValue("ip");

        cell = row.createCell(6);
        cell.setCellValue("system");

        cell = row.createCell(7);
        cell.setCellValue("number");

        cell = row.createCell(8);
        cell.setCellValue("result");

        try {
            for (int i = 0; i < list.size(); i++) {
                os = new ByteArrayOutputStream();
                row = xssfSheet.createRow(i + 1);

                cell = row.createCell(0);
                cell.setCellValue(list.get(i).getUserLogIndex());

                cell = row.createCell(1);
                cell.setCellValue(list.get(i).getUserIndex());

                cell = row.createCell(2);
                cell.setCellValue(list.get(i).getUserLogDescribe());

                cell = row.createCell(3);
                cell.setCellValue(list.get(i).getType());

                cell = row.createCell(4);
                cell.setCellValue(sqlFormat.format(list.get(i).getUpdateTime()));

                cell = row.createCell(5);
                cell.setCellValue(list.get(i).getIp());

                cell = row.createCell(6);
                cell.setCellValue(list.get(i).getSystem());

                cell = row.createCell(7);
                cell.setCellValue(list.get(i).getNumber());

                cell = row.createCell(8);
                cell.setCellValue(list.get(i).getResult());

                xssfWorkbook.write(os);
            }

            //设置response参数，可以打开下载界面
            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName + ".xlsx").getBytes(), "iso-8859-1"));
            ServletOutputStream out = response.getOutputStream();
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            byte[] content = os.toByteArray();
            is = new ByteArrayInputStream(content);
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(out);
            byte[] buff = new byte[2048];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
            bis.close();
            bos.close();
        } catch (IOException e) {
            logger.error("异常为：" + e.toString());
        }
    }

}
