package com.yfd.platform.system.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
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.yfd.platform.config.DatabaseConfigReader;
import com.yfd.platform.system.domain.SysDataBackup;
import com.yfd.platform.system.domain.SysLog;
import com.yfd.platform.system.mapper.SysDataBackupMapper;
import com.yfd.platform.system.service.ISysDataBackupService;
import com.yfd.platform.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * 系统数据备份恢复记录 服务实现类
 * </p>
 *
 *
 * @since 2023-08-31
 */
@Service
@Slf4j
public class SysDataBackupServiceImpl extends ServiceImpl<SysDataBackupMapper, SysDataBackup> implements ISysDataBackupService {

    @Resource
    private DatabaseConfigReader databaseConfigReader;

    @Override
    public Page<SysDataBackup> getBackFileList(String filename, String datascope, String backuptype, String startDate
            , String endDate, Page<SysDataBackup> page) {

        LambdaQueryWrapper<SysDataBackup> queryWrapper = new LambdaQueryWrapper<SysDataBackup>();
        if (StrUtil.isNotBlank(filename)) {
            queryWrapper.like(SysDataBackup::getFilename, filename);
        }
        // 没有传username就不按此条件查询
        if (StrUtil.isNotBlank(datascope)) {
            queryWrapper.eq(SysDataBackup::getDatascope, datascope);
        }
        //
        if (StrUtil.isNotBlank(backuptype)) {
            queryWrapper.eq(SysDataBackup::getBackuptype, backuptype);
        }


        if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
            DateTime parseStartDate = DateUtil.parse(startDate);
            DateTime parseEndDate = DateUtil.parse(endDate);
            DateTime dateTime = DateUtil.offsetDay(parseEndDate, 1);
            queryWrapper.ge(SysDataBackup::getBackupdate, parseStartDate).lt(SysDataBackup::getBackupdate, dateTime);
        }
        queryWrapper.orderByDesc(SysDataBackup::getBackupdate);
        return this.page(page, queryWrapper);
    }

    @Override
    public boolean backupDataTable(String datascope, String backuptype) {
        try {
            String url=databaseConfigReader.getDatabaseUrl();
            Pattern pattern = Pattern.compile("jdbc:mysql://(.*):(\\d+)/(\\w+)\\?");
            Matcher matcher = pattern.matcher(url);

            String ipAddress = "";
            int port = 0;
            String databaseName = "";
            if (matcher.find()) {
                 ipAddress = matcher.group(1);
                 port = Integer.parseInt(matcher.group(2));
                 databaseName = matcher.group(3);
            } else {
                log.error("URL format does not match.");
                return false;
            }

            String backupPath=databaseConfigReader.getBackupPath();

            StringBuilder command = new StringBuilder("mysqldump")
                    .append(" --host=").append(ipAddress)
                    .append(" --port=").append(port)
                    .append(" --user=").append(databaseConfigReader.getDatabaseUsername())
                    .append(" --password=").append(databaseConfigReader.getDatabasePassword())
                    .append(" ").append(databaseName);

            String[] tablesToBackup = {}; // 要备份的数据表名称数组
            if(datascope.equals("基础数据")){
                tablesToBackup = new String[]{"iis_substation", "iis_substation_area","iis_substation_bay","iis_substation_maindevice","iis_substation_component","iis_substation_device","iis_substation_patroldevice","iis_algorithm_model","mon_device","mon_device_channel",
                        "sys_config","sys_dictionary","sys_dictionary_items","sys_menu","sys_organization","sys_quartz_job","sys_role","sys_user","sys_role_menu","sys_role_patroldevice","sys_role_users"};
                for (String tableName : tablesToBackup) {

                    command.append(" ").append(tableName);
                }
            }else if(datascope.equals("业务数据")){
                tablesToBackup = new String[]{"iis_task", "iis_task_todo", "iis_task_result", "iis_alarm_log", "iis_examine_plan","iis_linkage_signal","iis_weather_log"};
                for (String tableName : tablesToBackup) {
                    command.append(" ").append(tableName);
                }
            }

            String filename= String.format("%s-%s-%s.sql",DateUtil.format(DateUtil.date(),"yyyyMMddHHmmss"),datascope,backuptype);
            FileUtil.touch(backupPath+filename);//创建多级目录
            command.append(" --result-file=").append(backupPath+filename);

            ProcessBuilder processBuilder = new ProcessBuilder(command.toString().split(" "));
            Process process = processBuilder.start();
            int exitCode = process.waitFor();

            if (exitCode == 0) {
                SysDataBackup sysDataBackup=new SysDataBackup();
                sysDataBackup.setDatascope(datascope);
                sysDataBackup.setFilename(filename);
                sysDataBackup.setBackuptype(backuptype);
                sysDataBackup.setBackupdate(DateUtil.toLocalDateTime(DateUtil.date()));
                File file = new File(backupPath+filename);
                if (file.exists()) {
                    long fileSizeInBytes = file.length();
                    long  fileSizeInKB = fileSizeInBytes / 1024;
                    sysDataBackup.setFilesize(fileSizeInKB+"KB");
                }
                this.save(sysDataBackup);
                log.info("Backup completed successfully.");
            } else {
                log.error("Backup failed.");
            }
        } catch (InterruptedException | IOException e) {
            log.error(e.getMessage());;
        }
        return true;
    }

    @Override
    public boolean recoverDataTable(String id) {
        SysDataBackup sysDataBackup = this.getById(id);
        String backupPath = databaseConfigReader.getBackupPath();
        String filefullname = backupPath + sysDataBackup.getFilename();
        if (StrUtil.isNotEmpty(filefullname)) {
        }
        return true;
    }

    /**********************************
     * 用途说明: 下载数据库文件
     * 参数说明 id 数据表备份文件记录id
     * 返回值说明: boolean 是否成功
     ***********************************/
    @Override
    public boolean downloadDataTable(String id, HttpServletResponse response) {
        SysDataBackup sysDataBackup = this.getById(id);
        String backupPath = databaseConfigReader.getBackupPath();
        String filefullname = backupPath + sysDataBackup.getFilename();
        if (StrUtil.isNotEmpty(filefullname)) {
            File file = new File(filefullname);
            FileUtil.downloadFile(null, response, file, false);
        }
        return true;
    }
}
