import * as mime from "mime-types";
import { delay } from "../../../baileys/lib";
import {
  deleteSession,
  getSession,
  jidExists,
  Session,
} from "./bot-whatsapp/wa";
import { wwebCleanNumber } from "./utils.whatsapp";
const { createWriteStream, rename } = require("fs");
const http = require("http");
const https = require("https");
const { tmpdir } = require("os");
const mimeDep = require("mime-types");
/**
 * Extrar el mimetype from buffer
 * @param {string} response
 * @returns
 */
const fileTypeFromFile = async (response) => {
  const type = response.headers["content-type"] ?? null;
  const ext = mimeDep.extension(type);
  return {
    type,
    ext,
  };
};
interface SendMessageWhatsappInterface {
  type: "number" | "group";
  location?: {
    lat: string;
    lon: string;
  };
  buttons?: {
    buttonId: string;
    buttonText: { displayText: string };
    type: number;
  }[];
  media?: string;
}

/**
 * Descargar archivo binay en tmp
 * @param {*} url
 * @returns
 */
const generalDownload = async (url) => {
  const handleDownload: any = () => {
    const checkProtocol = url.includes("https:");
    const handleHttp = checkProtocol ? https : http;
    const name = `tmp-${Date.now()}-dat`;
    const fullPath = `${tmpdir()}/${name}`;
    const file = createWriteStream(fullPath);

    return new Promise((res, rej) => {
      handleHttp.get(url, function (response) {
        response.pipe(file);
        file.on("finish", async function () {
          file.close();
          res({ response, fullPath });
        });
        file.on("error", function () {
          file.close();
          rej(null);
        });
      });
    });
  };

  const handleFile = (pathInput, ext) =>
    new Promise((resolve, reject) => {
      const fullPath = `${pathInput}.${ext}`;
      rename(pathInput, fullPath, (err) => {
        if (err) reject(null);
        resolve(fullPath);
      });
    });

  const httpResponse = await handleDownload();
  const { ext } = await fileTypeFromFile(httpResponse.response);
  const getPath = await handleFile(httpResponse.fullPath, ext);

  return getPath;
};

export class WebWhatsappProvider {
  session: Session;
  sessionId: string;
  constructor(sessionId: string) {
    this.session = getSession(sessionId);
  }

  async disconnect() {
    return deleteSession(this.sessionId);
  }

  async sendLocation(type, number, { lat, lon }, comment) {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }

    return await this.session.sendMessage(number, {
      location: { degreesLatitude: lat, degreesLongitude: lon, comment },
    });
  }

  /**
   * Enviar botones
   * https://docs.wwebjs.dev/Buttons.html
   * @private
   * @param {*} number
   * @param {*} message
   * @param {*} buttons []
   * @returns
   */
  sendButtons = async (type, number, message, buttons: any) => {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }

    return this.session.sendMessage(number, { text: message, buttons }, {});
  };

  /**
   * Enviar un mensaje solo texto
   * https://docs.wwebjs.dev/Message.html
   * @private
   * @param {*} number
   * @param {*} message
   * @returns
   */
  sendText = async (type, number, message) => {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }
    return await this.session.sendMessage(number, message, {});
  };

  /**
   * Enviar imagen
   * @param {*} number
   * @param {*} imageUrl
   * @param {*} text
   * @returns
   */
  sendImage = async (type, number, url, caption) => {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }
    return this.session.sendMessage(number, { image: { url }, caption }, {});
  };

  /**
   * Enviar audio
   * @param {*} number
   * @param {*} audioUrl
   * @param {*} text
   * @returns
   */
  sendAudio = async (type, number, url, caption) => {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }
    return this.session.sendMessage(number, { audio: { url }, caption }, {});
  };

  /**
   * Enviar video
   * @param {*} number
   * @param {*} videoUrl
   * @param {*} text
   * @returns
   */
  sendVideo = async (type, number, url, caption) => {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }
    return this.session.sendMessage(number, { video: { url }, caption }, {});
  };

  /**
   * Enviar Archivos/pdf
   * @param {*} number
   * @param {*} imageUrl
   * @param {*} text
   * @returns
   */
  sendFile = async (type, number, url, caption) => {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }
    const mimetype = mime.lookup(url);
    return this.session.sendMessage(
      number,
      { document: { url }, mimetype, caption },
      {}
    );
  };

  /**
   * Enviar imagen o multimedia
   * @param {*} number
   * @param {*} mediaInput
   * @param {*} message
   * @returns
   */
  sendMedia = async (type, number, mediaUrl, text) => {
    const exists = await jidExists(this.session, number, type);
    if (!exists) {
      return Error("JID does not exists");
    }
    await this.session.presenceSubscribe(number);
    await delay(500);

    await this.session.sendPresenceUpdate("composing", number);
    await delay(700);

    await this.session.sendPresenceUpdate("paused", number);
    // const fileDownloaded = await generalDownload(mediaUrl);
    const mimeType = mime.lookup(mediaUrl);

    if (mimeType.includes("image")) {
      return this.sendImage(type, number, mediaUrl, text);
    }
    if (mimeType.includes("video")) {
      return this.sendVideo(type, number, mediaUrl, text);
    }
    if (mimeType.includes("audio")) {
      return this.sendAudio(type, number, mediaUrl, text);
    }
    return this.sendFile(type, number, mediaUrl, text);
  };

  /**
   * Funcion SendRaw envia opciones directamente del proveedor
   * @param {string} number
   * @param {string} message
   * @example await sendMessage('+XXXXXXXXXXX', 'Hello World')
   */

  // sendRaw = () => this.vendor.sendMessage;
  /**
   *
   * @param {*} userId
   * @param {*} message
   * @param {*} param2
   * @returns
   */

  sendMessage = async (
    userId,
    message,
    options: SendMessageWhatsappInterface = { type: "number" }
  ) => {
    const number =
      userId !== "status@broadcast"
        ? wwebCleanNumber(userId)
        : "status@broadcast";
    if (options?.location) {
      return this.sendLocation(
        options.type,
        number,
        { lat: options?.location?.lat, lon: options.location?.lon },
        message.text
      );
    }
    if (options?.buttons?.length) {
      return this.sendButtons(options.type, number, message, options.buttons);
    }
    if (options?.media) {
      return this.sendMedia(options.type, number, options.media, message.text);
    }
    return this.sendText(options.type, number, message);
  };
  sendState = async (message) => {
    // this.vendor.setStatus(message);
  };
  sendStory = async (media) => {
    // const number = wwebCleanNumber("34642480131");
    // const photoBuffer = file.buffer as Buffer;
    // const base64 = photoBuffer.toString('base64');
    // const mimeType = file.mimetype;
    // const media = new MessageMedia(mimeType, base64);
    // const media = MessageMedia.fromUrl('https://fastly.picsum.photos/id/496/1000/1000.jpg?hmac=ywTDTNfBOA6neOtR1skTT7ITBiKA97CxRjxCsC5lRb0');
    // return this.vendor.sendMessage('status@broadcast', { media });
    // return this.sendMedia('status@broadcast', 'https://fastly.picsum.photos/id/496/1000/1000.jpg?hmac=ywTDTNfBOA6neOtR1skTT7ITBiKA97CxRjxCsC5lRb0', '')
    // const media1 = MessageMedia.fromUrl(
    //   "https://fastly.picsum.photos/id/496/1000/1000.jpg?hmac=ywTDTNfBOA6neOtR1skTT7ITBiKA97CxRjxCsC5lRb0"
    // );
    // this.vendor.setStatus(media1).then((a) => {
    //     console.log({ a })
    // }).catch((e) => {
    //     console.log({ e })
    // })
    // return await this.vendor.sendMessage(number, { media: media1 });
    // return this.vendor.sendMessage(number, { media });
  };
}
