import { NodeSSH } from 'node-ssh';
import path from 'node:path';
import fs from 'node:fs';
import process from 'node:process';

const loadConfig = async () => {
  try {
    const { default: config } = await import('./.deployrc.js');
    return config;
  } catch (error) {
    if (error.code !== 'ERR_MODULE_NOT_FOUND') throw error;

    return {
      host: process.env.DEPLOY_HOST,
      port: process.env.DEPLOY_PORT || 22,
      username: process.env.DEPLOY_USER,
      password: process.env.DEPLOY_PASSWORD,
      privateKey: process.env.DEPLOY_PRIVATE_KEY_PATH ? fs.readFileSync(path.resolve(process.env.DEPLOY_PRIVATE_KEY_PATH)) : null,
      remotePath: process.env.DEPLOY_REMOTE_PATH,
      cleanRemote: process.env.DEPLOY_CLEAN === 'true'
    };
  }
};

const ssh = new NodeSSH();

async function deploy() {
  try {
    const config = await loadConfig();
    validateConfig(config);

    console.log('🔄  Connecting to server...');
    await ssh.connect({
      host: config.host,
      port: config.port,
      username: config.username,
      password: config.password,
      privateKey: config.privateKey
    });

    console.log('📂  Ensuring remote directory exists...');
    await ssh.execCommand(`mkdir -p ${config.remotePath}`);

    if (config.cleanRemote) {
      console.log('🧹  Cleaning remote directory...');
      await ssh.execCommand(`rm -rf ${config.remotePath}/*`);
    }

    console.log('🚀  Uploading files...');
    const uploadResult = await ssh.putDirectory('./dist', config.remotePath, {
      recursive: true,
      concurrency: 10,
      tick: (localPath, remotePath, error) => {
        const relativePath = path.relative(process.cwd(), localPath);
        console[error ? 'error' : 'log'](`${error ? '❌' : '✅'} ${error ? 'Failed' : 'Uploaded'}: ${relativePath}`);
      }
    });

    if (!uploadResult) throw new Error('Upload failed without specific error');

    console.log('🎉  Deployment completed successfully!');
  } catch (error) {
    console.error('🔥  Deployment failed:', error.message);
    process.exit(1);
  } finally {
    ssh.dispose();
  }
}

function validateConfig(config) {
  const requiredFields = ['host', 'username', 'remotePath'];
  const missing = requiredFields.filter((field) => !config[field]);

  if (missing.length) {
    throw new Error(`Missing required config fields: ${missing.join(', ')}`);
  }

  if (!config.password && !config.privateKey) {
    throw new Error('Either password or privateKey must be provided');
  }
}

// 执行部署
deploy();
