import { SQSClient, ReceiveMessageCommand } from "@aws-sdk/client-sqs";
import config from "../config.ts";
import { createInterface } from "node:readline";
import { stdin as input, stdout as output } from "node:process";

type ReceivedMessage = {
  MessageId?: string;
  Body?: string;
};

const sqsClient = new SQSClient({
  region: config.aws.region,
  credentials: {
    accessKeyId: config.aws.accessKeyId,
    secretAccessKey: config.aws.secretAccessKey,
  },
});

async function receiveMessages(
  desiredCount: number
): Promise<ReceivedMessage[]> {
  const collected: ReceivedMessage[] = [];
  let remaining = Math.max(0, desiredCount);

  while (remaining > 0) {
    const batchSize = Math.min(10, remaining);
    const cmd = new ReceiveMessageCommand({
      QueueUrl: config.aws.queueUrl,
      MaxNumberOfMessages: batchSize,
      WaitTimeSeconds: 10, // long polling
      MessageAttributeNames: ["All"],
    });

    const res = await sqsClient.send(cmd);
    const msgs = res.Messages ?? [];
    if (msgs.length === 0) break;

    for (const m of msgs) {
      collected.push({ MessageId: m.MessageId, Body: m.Body });
    }

    remaining -= msgs.length;
  }

  return collected;
}

function parsePositiveInt(text: string): number | null {
  const n = Number(text.trim());
  if (!Number.isFinite(n)) return null;
  if (!Number.isInteger(n)) return null;
  if (n <= 0) return null;
  return n;
}

function printMessages(messages: ReceivedMessage[]): void {
  if (messages.length === 0) {
    console.log("No messages received.");
    return;
  }

  console.log(`\nReceived ${messages.length} message(s):`);
  messages.forEach((m, idx) => {
    let bodyToShow: string = m.Body ?? "";
    try {
      // Pretty print JSON bodies when possible
      bodyToShow = JSON.stringify(JSON.parse(bodyToShow), null, 2);
    } catch {
      // keep as is
    }

    console.log(`\n#${idx + 1}`);
    console.log(`MessageId: ${m.MessageId ?? ""}`);
    console.log("Body:");
    console.log(bodyToShow);
  });
  console.log("");
}

async function main(): Promise<void> {
  const rl = createInterface({ input, output });

  console.log("Interactive SQS puller (non-destructive). Type 'q' to quit.\n");

  const ask = (q: string) =>
    new Promise<string>((resolve) => rl.question(q, resolve));

  try {
    while (true) {
      const answer = (
        await ask("How many messages to pull? (1-... or q): ")
      ).trim();
      if (answer.toLowerCase() === "q") break;

      const count = parsePositiveInt(answer);
      if (count === null) {
        console.log("Please enter a positive integer or 'q' to quit.\n");
        continue;
      }

      console.log(`\nPulling up to ${count} message(s)...`);
      try {
        const messages = await receiveMessages(count);
        printMessages(messages);
      } catch (err) {
        console.error("Error receiving messages:", err);
      }
    }
  } finally {
    rl.close();
  }

  console.log("Goodbye.");
}

// Run if called directly
main().catch((err) => {
  console.error(err);
  process.exitCode = 1;
});
