import { exec } from 'child_process'
import { Client as SSHClient } from 'ssh2'
import ora from 'ora'
import SftpClient from 'ssh2-sftp-client'
import chalk from 'chalk'
import fs from 'fs'
import { loadEnv } from 'vite'

// 存储原始的 接口请求地址
let originalApiUrl = '';

// 创建分隔线
const createSeparator = (text) => {
  const width = 60;
  const padding = Math.floor((width - text.length - 2) / 2);
  const separator = '='.repeat(padding) + ' ' + text + ' ' + '='.repeat(padding);
  return chalk.blue('\n' + separator + '\n');
};


const spinner = ora('正在构建项目...').start()
spinner.stopAndPersist({
  text:
    ' __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ \n' +
    ' |                                                          |\n' +
    ' |                    *** 运行发布流程 ***                   |\n' +
    ' |                      【pigx管理系统】                     |\n' +
    ' | __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ |\n'
})

spinner.start()
let speed = 20
let time = 20
const count = 400
const getProgress = () => {
  const done = '█'
  const undone = '░'
  let progress = Math.floor((speed / count) * 50)
  if (progress > 50) {
    progress = 50
  }
  const progressBar = done.repeat(progress) + undone.repeat(50 - progress)
  return progressBar
}
const interval = setInterval(() => {
  spinner.text = `正在构建项目 ${getProgress()} 进度${((speed / count) * 100).toFixed(1)}% 耗时${(time / 10).toFixed(1)}秒 `
  speed++
  time++
  if (speed > count) {
    speed = 400
  }
}, 100)
const env = loadEnv('', process.cwd())

const updateProxyConfig = (url) => {
  try {
    const envPath = '.env';
    let content = fs.readFileSync(envPath, 'utf-8');

    // 提取当前的 apiBaseUrl (如果需要)
    const match = content.match(/VITE_API_URL = (.*)/);
    if (!originalApiUrl && match && match[1]) {
      originalApiUrl = match[1];
      console.log(chalk.gray(`原始 API 地址已保存: ${originalApiUrl}`));
    }

    // 使用正则表达式替换apiBaseUrl的值，但保留注释
    content = content.replace(
      /VITE_API_URL = (.*)/,
      `VITE_API_URL = ${url}`
    );

    fs.writeFileSync(envPath, content, 'utf-8');
    console.log(chalk.green('✓'), chalk.blue(`已更新 API 地址为: ${url}`));
  } catch (error) {
    console.error(chalk.red('✗'), chalk.red('更新 API 地址失败:'), error);
    process.exit(1);
  }
};

const command = (list, config, host) => {
  return new Promise((resolveCommand, rejectCommand) => {
    const ssh = new SSHClient();

    const runCommand = (index) => {
      if (index >= list.length) {
        ssh.end();
        console.log(chalk.green('✓'), chalk.blue(`端口 ${host} 的远程命令执行完毕`));
        resolveCommand();
        return;
      }
      const cmd = list[index];
      console.log(chalk.blue('→'), chalk.gray(`执行命令: ${cmd}`));
      ssh.exec(cmd, (err, stream) => {
        if (err) {
          console.error(chalk.red('✗'), chalk.red(`命令执行失败: ${err}`));
          ssh.end();
          rejectCommand(err);
          return;
        }
        let hasError = false;
        stream.on('close', (code, signal) => {
          if (hasError && !cmd.includes('docker build')) {
            console.error(chalk.red('✗'), chalk.red(`命令执行失败，退出码: ${code}`));
            ssh.end();
            rejectCommand(new Error(`命令 "${cmd}" 失败，退出码: ${code}`));
            return;
          }
          console.log(chalk.green('✓'), chalk.gray(`命令执行完成: ${cmd}`));
          runCommand(index + 1);
        }).on('data', (data) => {
          console.log(chalk.gray(data.toString())); // 实时输出命令结果
        }).stderr.on('data', (data) => {
          hasError = true;
          console.error(chalk.yellow('!'), chalk.yellow(data.toString())); // 实时输出错误信息
        });
      });
    };

    ssh.on('ready', () => {
      console.log(chalk.green('✓'), chalk.blue('SSH 连接成功'));
      runCommand(0);
    }).connect(config);

    // Handle SSH connection errors
    ssh.on('error', (err) => {
      console.error(chalk.red('✗'), chalk.red('SSH 连接错误:'), err);
      rejectCommand(err);
    });
  });
};

const updateFiles = async () => {
  spinner.text = '正在链接服务器...';
 
  const config = {
     host: env.VITE_HOST,
    port: env.VITE_POST,
    username: env.VITE_USERNAME,
    password: env.VITE_PASSWORD
  };
  const sftp = new SftpClient();

  if (!fs.existsSync('dist')) {
    console.error(chalk.red('✗'), chalk.red('构建目录不存在'));
    spinner.fail('构建目录不存在');
    spinner.stopAndPersist({ text: '' }); // 停止并清理 spinner
    return;
  }

  try {
    await sftp.connect(config);
    spinner.succeed(chalk.green('服务器连接成功'));
    console.log(chalk.blue('→'), chalk.gray('开始上传文件...'));
    await sftp.uploadDir('dist_6888', '/data/seo-vue/dist');
    console.log(chalk.green('✓'), chalk.blue('6888端口文件上传完成'));
    await sftp.uploadDir('dist_16888', '/data/seo-vue-test/dist');
    console.log(chalk.green('✓'), chalk.blue('16888端口文件上传完成'));
   

    sftp.end();

    console.log(createSeparator('开始部署 6888 端口'));
    await command([
      "cd /data/seo-vue && pwd",
      "cd /data/seo-vue && ls -la",
      "cd /data/seo-vue && docker rm -f seo-vue",
      "cd /data/seo-vue && docker rmi seo-vue",
      "cd /data/seo-vue && docker build -t seo-vue .",
      "cd /data/seo-vue && docker run -d --name seo-vue -p 6888:80 seo-vue"
    ], config, "6888");
    console.log(createSeparator('6888 端口部署完成'));

    console.log(createSeparator('开始部署 16888 端口'));
    await command([
      "cd /data/seo-vue-test && pwd",
      "cd /data/seo-vue-test && ls -la",
      "cd /data/seo-vue-test && docker rm -f seo-vue-test",
      "cd /data/seo-vue-test && docker rmi seo-vue-test",
      "cd /data/seo-vue-test && docker build -t seo-vue-test .",
      "cd /data/seo-vue-test && docker run -d --name seo-vue-test -p 16888:80 seo-vue-test"
    ], config, "16888");
    console.log(createSeparator('16888 端口部署完成'));
   

  } catch (err) {
    console.error(chalk.red('✗'), chalk.red('部署或文件上传失败:'), err);
    spinner.fail(err);
    spinner.stopAndPersist({ text: '' }); // 停止并清理 spinner
    sftp.end();
    throw err; // 向上抛出错误，让main函数捕获并处理退出
  }
};
// 项目构建
console.log(createSeparator('开始构建项目'));

// 使用 Promise 包装构建过程
const buildWithProgress = (port, apiUrl) => {
  return new Promise((resolve, reject) => {
     console.log(chalk.blue(`\n构建 ${port} 端口版本`));
    console.log(chalk.gray(`API 地址: ${apiUrl}`));
    updateProxyConfig(apiUrl);
    // 重置进度条
    speed = 20;
    time = 20;
    spinner.start(); // 确保每次构建前启动 spinner
    const buildProcess = exec('npm run build');
    let buildOutput = '';

    buildProcess.stdout.on('data', (data) => {
      buildOutput += data;
      // 根据输出更新进度
      if (data.includes('compiled successfully')) {
        speed = count;
      }
    });

    buildProcess.stderr.on('data', (data) => {
      buildOutput += data;
    });

    buildProcess.on('close', async (code) => {
      if (code === 0) {
           // 构建成功后，将dist目录复制到对应的端口目录
        const distDir = 'dist';
        const targetDir = `dist_${port}`;

        try {
          // 如果目标目录已存在，先删除
          if (fs.existsSync(targetDir)) {
            fs.rmSync(targetDir, { recursive: true, force: true });
          }
          // 复制dist目录到目标目录
          fs.cpSync(distDir, targetDir, { recursive: true });
          console.log(chalk.green('✓'), chalk.blue(`已保存 ${port} 端口构建文件到 ${targetDir}`));
        } catch (err) {
          console.error(chalk.red('✗'), chalk.red(`保存构建文件失败: ${err}`));
          reject(err);
          return;
        }


        spinner.succeed(chalk.green(`构建成功`));
        resolve(buildOutput);
      } else {
        spinner.fail(chalk.red(`构建失败`));
        reject(new Error(buildOutput));
      }
    });
  });
};

// 主构建流程
const main = async () => {
  spinner.start(); // 在主流程开始时启动 spinner，用于总体的进度指示
  try {
      const envPath = '.env';
    const content = fs.readFileSync(envPath, 'utf-8');
    const match = content.match(/VITE_API_URL = (.*)/);
    if (match && match[1]) {
      originalApiUrl = match[1];
    } else {
      console.warn(chalk.yellow('!'), chalk.yellow('无法从 env 中读取原始 VITE_API_URL，可能无法还原。'));
    }

    // 构建 6888 端口版本
    await buildWithProgress('6888', 'http://192.168.10.101:9999');
    // 构建 16888 端口版本
    await buildWithProgress('16888', 'http://192.168.3.17:9999');

    // 开始部署
    await updateFiles();

    // 所有任务完成后，打印最终访问路径并停止 spinner
    clearInterval(interval); // 在所有任务完成后停止进度条动画
    console.log(createSeparator('部署完成'));
    console.log(chalk.green('🎉'), chalk.cyan('所有环境部署成功!'));
    console.log(chalk.green('🚀'), chalk.cyan(`6888 端口访问地址: http://${env.VITE_HOST}:6888`));
    console.log(chalk.green('🚀'), chalk.cyan(`16888 端口访问地址: http://${env.VITE_HOST}:16888`));
       // 还原 VITE_API_URL 到原始值
    if (originalApiUrl) {
      console.log(createSeparator('还原配置'));
      updateProxyConfig(originalApiUrl);
    } else {
      console.warn(chalk.yellow('!'), chalk.yellow('未找到原始 VITE_API_URL，跳过还原。'));
    }

    
    spinner.stopAndPersist({ text: '' }); // 停止并清理 spinner，返回控制台
    process.exit(0); // 正常退出，返回控制台
  } catch (error) {
    console.error(chalk.red('✗'), chalk.red('发布流程出错:'), error);
    spinner.fail(error);
    spinner.stopAndPersist({ text: '' }); // 停止并清理 spinner，返回控制台
    process.exit(1); // 异常退出
  }};

// 启动主流程
main();