/**
 * Reimplementation of string-crypto v2 encryption
 * Uses Node's built-in crypto module (works in Bun too)
 */

import {
  randomBytes,
  pbkdf2Sync,
  createCipheriv,
  createDecipheriv,
} from "crypto";

const KEYLEN = 256 / 8; // 32 bytes for aes-256

interface DeriveKeyOpts {
  salt?: string;
  iterations?: number;
  digest?: string;
}

const defaultOpts: DeriveKeyOpts = {
  salt: "s41t",
  iterations: 1,
  digest: "sha512",
};

export function deriveKey(password: string, options?: DeriveKeyOpts): Buffer {
  const { salt, iterations, digest } = { ...defaultOpts, ...options };
  return pbkdf2Sync(password, salt!, iterations!, KEYLEN, digest!);
}

export function encryptString(str: string, password: string): string {
  const derivedKey = deriveKey(password);
  const iv = randomBytes(16);

  const cipher = createCipheriv("aes-256-gcm", derivedKey, iv);

  let encryptedBase64 = cipher.update(str, "utf8", "base64");
  encryptedBase64 += cipher.final("base64");

  // Convert base64 to hex (this is the v2 quirk)
  const encryptedHex = Buffer.from(encryptedBase64).toString("hex");
  const ivHex = iv.toString("hex");

  return `${ivHex}:${encryptedHex}`;
}

export function decryptString(encryptedStr: string, password: string): string {
  const derivedKey = deriveKey(password);
  const [ivHex, encryptedHex] = encryptedStr.split(":");

  const iv = Buffer.from(ivHex, "hex");
  const encryptedBase64 = Buffer.from(encryptedHex, "hex").toString();

  const decipher = createDecipheriv("aes-256-gcm", derivedKey, iv);

  let decrypted = decipher.update(encryptedBase64, "base64", "utf8");
  return decrypted;
}

// Test
if (import.meta.main) {
  // Load .env
  const envFile = Bun.file(".env");
  if (await envFile.exists()) {
    const envContent = await envFile.text();
    for (const line of envContent.split("\n")) {
      const [key, ...valueParts] = line.split("=");
      if (key && valueParts.length) {
        process.env[key.trim()] = valueParts.join("=").trim();
      }
    }
  }

  const email = process.env.ANYCLIP_EMAIL || process.env.ANYCLIP_USER;
  const plaintext = process.env.ANYCLIP_PASSWORD;

  if (!email || !plaintext) {
    console.error("Set ANYCLIP_EMAIL and ANYCLIP_PASSWORD in .env");
    process.exit(1);
  }

  const salt = "$2b$04$wwky7rvtr6BFNaCqntwyie";
  const encrypted = encryptString(plaintext, salt);
  console.log("Encrypted:", encrypted);

  // Test with API
  console.log("\nTesting with AnyClip API...");
  const response = await fetch(
    "https://videomanager-api.anyclip.com/public/auth/login",
    {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        email,
        password: encrypted,
      }),
    }
  );

  console.log("Status:", response.status);
  if (response.ok) {
    console.log("✅ Works without string-crypto library!");
  } else {
    const text = await response.text();
    console.log("Response:", text);
  }
}
