const Redis = require("ioredis");
const redis = new Redis(process.env.REDIS_URI);

type WhatsappData = {
  whatsappId: string;
  contactId: string;
  identifier: string;
  value?: string;
  history?: string;
};

type getData = {
  key: string;
  value?: string;
  parse?: boolean;
};

export async function set(key: string, value: string | object) {
  if (typeof value == "object") await redis.set(key, JSON.stringify(value));
  else {
    await redis.set(key, value);
  }
}

export async function getSimple(key: string) {
  const value: any = await redis.get(key);
  return value;
}

export async function get({ key, value, parse }: getData) {
  if (key.includes("*")) {
    const keys = await redis.keys(key);
    if (keys.length > 0) {
      if (value) {
        for (const key of keys) {
          const val = await redis.get(key);
          if (val.includes(value)) {
            if (parse) return JSON.parse(val);
            return val;
          }
        }
      } else {
        let res: any[] = [];
        for (const key of keys) {
          const val = await redis.get(key);
          if (parse) res.push(JSON.parse(val));
          res.push(val);
        }
        return res;
      }
    }
    return null;
  } else {
    const value: any = await redis.get(key);

    if (parse) return JSON.parse(value);

    return value;
  }
}

export async function del(key: string) {
  await redis.del(key);
}

export async function clearAllKeys(...keys: string[]) {
  for (const key of keys) {
    // Retrieve all keys matching the pattern '*'
    const del_keys = await redis.keys(key);

    // If there are keys, delete them
    if (del_keys.length > 0) {
      // console.log("del_keys: ", del_keys);
      await redis.del(...del_keys);
    }
  }
}

export async function findByContain(
  key: string,
  keyName: string,
  substring: string
) {
  // const keys = await redis.keys("*" + substring + "*");
  // const keys = await redis.keys("user:*");

  const keys = await redis.keys(key);

  const results: any[] = [];

  for (const key of keys) {
    const value = await redis.get(key);
    if (value) {
      const obj = JSON.parse(value);
      if (
        substring
          ?.trim()
          ?.toLowerCase()
          .includes(obj[keyName]?.trim()?.toLowerCase())
      ) {
        results.push(obj);
      }
    }
  }
  return results;
}

export async function createObject({
  whatsappId,
  contactId,
  identifier,
  value,
  history = ""
}: WhatsappData) {
  const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
  const result = await redis.hmset(
    key,
    "whatsappId",
    whatsappId,
    "contactId",
    contactId,
    "identifier",
    identifier,
    "value",
    value,
    "history",
    history
  );

  await redis.expire(key, 300);
}

export async function updateObject({
  whatsappId,
  contactId,
  identifier,
  value
}: WhatsappData) {
  const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;

  await redis.hset(key, "value", value);
}

export async function findObject(
  whatsappId: string,
  contactId: string,
  identifier: string
) {
  const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
  const result = await redis.hmget(
    key,
    "whatsappId",
    "contactId",
    "identifier",
    "value",
    "history"
  );
  return result;
}

export async function deleteObject(
  whatsappId: string,
  contactId: string,
  identifier: string
) {
  const key = `whatsappId:${whatsappId}:contactId:${contactId}:identifier:${identifier}`;
  const deletedCount = await redis.del(key);
}

export async function deleteKeysWithPattern(
  whatsappId: string,
  contactId: string
) {
  const pattern = `whatsappId:${whatsappId}:contactId:${contactId}:*`;

  let cursor = "0";

  do {
    const [newCursor, keys] = await redis.scan(
      cursor,
      "MATCH",
      pattern,
      "COUNT",
      "100"
    );

    for (const key of keys) {
      await redis.del(key);
    }

    cursor = newCursor;
  } while (cursor !== "0");
}

export async function getHashesWithPattern(
  whatsappId: string,
  contactId: string
) {
  const pattern = `whatsappId:${whatsappId}:contactId:${contactId}:*`;

  let cursor = "0";
  const hashes = [];

  do {
    const [newCursor, keys] = await redis.scan(
      cursor,
      "MATCH",
      pattern,
      "COUNT",
      "100"
    );

    for (const key of keys) {
      const hash = await redis.hgetall(key);
      hashes.push(hash);
    }

    cursor = newCursor;
  } while (cursor !== "0");

  return hashes;
}

 
