import config from "../config.ts";
import axios from "axios";
import * as fs from "fs";
import * as path from "path";
import { v4 as uuidv4 } from "uuid";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs";
import cliProgress from "cli-progress";

const count = 1000;
const bs = 10;

/**
 * Uploads a string payload to an AWS SQS queue using configuration from config.ts.
 *
 * @param payload - The string payload to be uploaded.
 * @returns A promise that resolves when the message is sent.
 */
export async function uploadStringToSqs(payload: string): Promise<void> {
  try {
    // Configure the SQS client with credentials and region from config.
    const client = new SQSClient({
      region: config.aws.region,
      credentials: {
        accessKeyId: config.aws.accessKeyId,
        secretAccessKey: config.aws.secretAccessKey,
      },
    });

    // Create the command to send a message.
    const command = new SendMessageCommand({
      QueueUrl: config.aws.queueUrl,
      MessageBody: payload,
    });

    // Send the message to the queue.
    const response = await client.send(command);

    console.log("Successfully sent message to SQS.");
    console.log("Message ID:", response.MessageId);
  } catch (error) {
    console.error("Error uploading message to SQS:", error);
  }
}

async function uploadFile(localPath: string, S3URL: string): Promise<void> {
  // Parse URL -> bucket/key
  const url = new URL(S3URL);
  const bucket = url.hostname.split(".")[0];
  const key = url.pathname.startsWith("/")
    ? url.pathname.slice(1)
    : url.pathname;

  // Basic existence check
  await fs.promises.access(localPath, fs.constants.F_OK);

  // Infer content type from extension
  const ext = path.extname(localPath).toLowerCase();
  const contentType =
    ext === ".png"
      ? "image/png"
      : ext === ".jpg" || ext === ".jpeg"
      ? "image/jpeg"
      : ext === ".webp"
      ? "image/webp"
      : ext === ".gif"
      ? "image/gif"
      : ext === ".svg"
      ? "image/svg+xml"
      : "application/octet-stream";

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

  const bodyStream = fs.createReadStream(localPath);
  const putCmd = new PutObjectCommand({
    Bucket: bucket,
    Key: key,
    Body: bodyStream,
    ContentType: contentType,
  });

  await s3.send(putCmd);
}

async function uploadToEspo(calenndarData: any) {
  const response = await axios.post(
    "https://cam5.pixika.ai/api/v1/CSubmission",
    calenndarData,
    {
      headers: { "x-api-key": config.espo.key },
    }
  );

  return response.data.id;
}

/**
 * Selects a random element from a given array.
 *
 * @template T The type of the elements in the array.
 * @param {T[]} arr The array of elements to choose from.
 * @returns {T | undefined} A randomly selected element from the array, or undefined if the array is empty.
 */
function selectRandom<T>(arr: T[]): T | undefined {
  // Return undefined if the array is empty to prevent an error.
  if (arr.length === 0) {
    return undefined;
  }

  // Generate a random index within the bounds of the array.
  const randomIndex = Math.floor(Math.random() * arr.length);

  // Return the element at the random index.
  return arr[randomIndex];
}

async function createDummyEntry() {
  const calendarUUID = uuidv4();
  const faceURL = `https://pixika5-live.s3.ap-south-1.amazonaws.com/uploads/Palsons_Derma_Pvt_Ltd_Palsons_Derma_DIY_Calendar_1374/MEET003/dummy-${calendarUUID}.png`;

  await uploadFile("./example-face.jpg", faceURL);

  const calendarData = {
    calendarOpton: "Fully Personalized by AI",
    token: "55227a7c003a4c63a35d50c91f95a1b9",
    dataStage: "COLLECTION-DONE",
    stitchStage: "NA",
    outputFormat: "pdf",
    region: "Maharashtra",
    size: 0,
    slot: "SLOT02",
    lang: "en",
    product: "CALENDAR 2025",
    groupBasis: "Maharashtra",
    previewTheme: null,
    deliverable: null,
    representativeId: "67bc31946fad30e61",
    projectId: "67b714af6fb414aed",
    empid: "999999",
    area: "Goregaon",
    zone: "Mumbai West",
    hq: "Mumbai",
    title: "Dr.",
    gender: "male",
    fullName: `testing ${calendarUUID}`,
    extid: calendarUUID.slice(0, 8),
    dob: "2025-09-01",
    anniversary: "2025-09-03",
    planner: "Scientific",
    ef1: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/1.png",
    ef2: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/2.png",
    ef3: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/3.png",
    ef4: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/6.png",
    ef5: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/5.png",
    ef6: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/4.png",
    ef7: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/7.png",
    ef8: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/8.png",
    ef9: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/9.png",
    ef10: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/12.png",
    ef11: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/11.png",
    ef12: "https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/professional/male/square/10.png",
    category: '["indian_culture_heritage","fine_art","people_portraits"]',
    orientation: "square",
    personalisedCalendarOption: "AI Face Swap Calendar",
    faceImageURL: faceURL,
    aiFeatureStage: "DATA-READY",
    description: '["professional","bollywood","sports","superheros"]',
  };

  const selectedCategory = selectRandom([
    "professional",
    "bollywood",
    "sports",
    "superheros",
  ]);
  const selectedGender = selectRandom(["male", "female"]);
  const selectedOrientation = selectRandom(["square", "portrait"]);

  for (let i = 0; i < 12; i++) {
    calendarData[
      `ef${i + 1}`
    ] = `https://pixika5-live.s3.ap-south-1.amazonaws.com/assets/calendar/faceswap/${selectedCategory}/${selectedGender}/${selectedOrientation}/${
      i + 1
    }.png`;
  }

  const calendarID = await uploadToEspo(calendarData);

  await uploadStringToSqs(`"${calendarID}"`);

  return calendarID;
}

// uploadFile(
//   "./example-face.png",
//   "https://pixika5-live.s3.ap-south-1.amazonaws.com/uploads/Palsons_Derma_Pvt_Ltd_Palsons_Derma_DIY_Calendar_1374/MEET003/face_1756356319918.png"
// );

// createDummyEntry().then(console.log);

// create the entries
(async () => {
  const totalBatches = Math.ceil(count / bs);

  // Create a progress bar
  const progressBar = new cliProgress.SingleBar({
    format:
      "Processing Entries |{bar}| {percentage}% | {value}/{total} batches | ETA: {eta}s",
    barCompleteChar: "\u2588",
    barIncompleteChar: "\u2591",
    hideCursor: true,
  });

  // Initialize the progress bar
  progressBar.start(totalBatches, 0);

  try {
    for (let i = 0; i < count; i += bs) {
      const batch: Promise<any>[] = [];
      const batchSize = Math.min(bs, count - i); // Handle last batch potentially being smaller

      for (let j = 0; j < batchSize; j++) {
        batch.push(createDummyEntry());
      }

      await Promise.all(batch);

      // Update progress bar
      const currentBatch = Math.floor(i / bs) + 1;
      progressBar.update(currentBatch);
    }

    progressBar.stop();
    console.log("\n✅ All entries processed successfully!");
  } catch (error) {
    progressBar.stop();
    console.error("\n❌ Error processing entries:", error);
    throw error;
  }
})();
