import { NodeSSH } from "node-ssh";
import { decrypt } from "@/lib/crypto/aes";

export interface SSHTarget {
  host: string;
  sshPort: number;
  sshUser: string;
  authMode: "password" | "key";
  authBlob: string; // encrypted JSON: {password?, privateKey?}
}

interface AuthBlob {
  password?: string;
  privateKey?: string;
}

function authConfig(t: SSHTarget) {
  const auth: AuthBlob = JSON.parse(decrypt(t.authBlob));
  return {
    host: t.host,
    port: t.sshPort,
    username: t.sshUser,
    ...(t.authMode === "password"
      ? { password: auth.password }
      : { privateKey: auth.privateKey }),
    readyTimeout: 15_000,
  };
}

export async function runRemote(
  t: SSHTarget,
  cmd: string,
  onLine?: (line: string) => void,
): Promise<{ code: number; stdout: string; stderr: string }> {
  const ssh = new NodeSSH();
  await ssh.connect(authConfig(t));
  let stdout = "";
  let stderr = "";
  const result = await ssh.execCommand(cmd, {
    onStdout(b) {
      const s = b.toString();
      stdout += s;
      if (onLine) s.split("\n").forEach((l) => l && onLine(l));
    },
    onStderr(b) {
      const s = b.toString();
      stderr += s;
      if (onLine) s.split("\n").forEach((l) => l && onLine(l));
    },
  });
  ssh.dispose();
  return { code: result.code ?? 0, stdout, stderr };
}

export async function putFile(
  t: SSHTarget,
  localPath: string,
  remotePath: string,
): Promise<void> {
  const ssh = new NodeSSH();
  await ssh.connect(authConfig(t));
  await ssh.putFile(localPath, remotePath);
  ssh.dispose();
}
