import { v4 as uuid } from 'uuid';
import { apiShopeeSeller } from '@/api/shopee/seller/init';
import { validatorSendMessage } from '@/validator/shopee/seller/chat';
import { renderPayloadSend, readySendChat } from './render';

const VERSION = '8.8.9';
const SOURCE = 'sc';
const SHOP_REGION = 'VN';
const WEBCHAT_AUTH_ERROR = 'WEBCHAT_AUTH_ERROR';

const validateAuth = (userId, ctoken, authorization) => {
  if (!(userId && ctoken && authorization)) {
    throw WEBCHAT_AUTH_ERROR;
  }
};

const buildConversationQuery = (userId, ctoken, spcCdsChat) => ({
  _uid: `1-${userId}`,
  _v: VERSION,
  csrf_token: ctoken,
  SPC_CDS_CHAT: spcCdsChat,
  'x-shop-region': SHOP_REGION,
  _api_source: SOURCE,
});

const buildConversationHeaders = (authorization) => ({
  authorization: `Bearer ${authorization}`,
  'content-type': 'text/plain;charset=UTF-8',
  'x-shop-region': SHOP_REGION,
});

const buildConversationPayload = (userId, ctoken, authorization) => {
  const spcCdsChat = uuid();
  const query = buildConversationQuery(userId, ctoken, spcCdsChat);
  const headers = buildConversationHeaders(authorization);

  return {
    headers,
    params: query,
  };
};

/**
 *
 * @param {number} toUserId
 * @param {number} toShopId
 * @param {string} text
 * @param {("text" | "sticker")} type
 * @param {object} sendOption
 * @param {string} conversationId
 * @returns {Promise<ShopeeWebchatSentResponse>}
 */
export const sendChatMessage = async (toUserId, toShopId, text, type = 'text', sendOption = {}, conversationId = '') => {
  await validatorSendMessage.validateAsync({
    toUserId,
    toShopId,
  });

  if (type === 'text' && !text) {
    throw new Error('Text is required');
  } else if (type === 'sticker' && !sendOption.stickerId) {
    throw new Error('StickerId is required');
  } else if (type === 'image' && !sendOption.imageId) {
    throw new Error('ImageId is required');
  } else if (type === 'product' && !sendOption.productId) {
    throw new Error('ProductId is required');
  } else if (type === 'voucher' && !sendOption.voucherId) {
    throw new Error('VoucherId is required');
  }

  const uri = '/webchat/api/v1.2/mini/messages';

  const payloadSend = {
    to_id: toUserId,
    shop_id: toShopId,
    type,
    content: {
      text,
      uid: uuid(),
    },
    request_id: uuid(),
    chat_send_option: {
      force_send_cancel_order_warning: false,
      comply_cancel_order_warning: false,
    },
    entry_point: 'direct_chat_entry_point',
    choice_info: {
      real_shop_id: null,
    },
    biz_id: 0,
    source: 'minichat',
  };

  if (type === 'sticker') {
    payloadSend.content.sticker_id = sendOption.stickerId;
    payloadSend.content.sticker_package_id = sendOption.stickerPackage;

    delete payloadSend.content.text;
  } else if (type === 'image') {
    payloadSend.content.image_id = sendOption.imageId;
    payloadSend.content.url = `https://down-sg.img.susercontent.com/${sendOption.imageId}`;

    delete payloadSend.content.text;
  } else if (type === 'product') {
    payloadSend.content.product_id = sendOption.productId;
    payloadSend.content.shop_id = sendOption.shopId;
    payloadSend.content.product_name = sendOption.productName;

    delete payloadSend.content.text;
  } else if (type === 'voucher') {
    payloadSend.content.voucher_id = sendOption.voucherId;
    payloadSend.content.voucher_code = sendOption.voucherCode;
    payloadSend.content.source = 'webchat';

    delete payloadSend.content.text;
  }

  if (conversationId) {
    payloadSend.conversation_id = conversationId;
  }

  const timestamp = Date.now();
  const { userId, ctoken, authorization } = await readySendChat();

  validateAuth(userId, ctoken, authorization);

  const { query, headers } = renderPayloadSend({
    userId,
    ctoken,
    body: payloadSend,
    timestamp,
    authorization,
  });

  const payload = {
    headers,
    params: query,
  };

  const result = await apiShopeeSeller.post(uri, payloadSend, payload);

  return result;
};

/**
 *
 * @param {Blob} blobImage
 * @returns {Promise<string>}
 */
export const uploadImageWebchat = async (blobImage) => {
  const payloadUpload = new FormData();
  payloadUpload.append('file', blobImage);

  const uri = '/webchat/api/coreapi/v1.2/images';

  const { userId, ctoken, authorization } = await readySendChat();

  validateAuth(userId, ctoken, authorization);

  const payloadAuthRender = buildConversationPayload(userId, ctoken, authorization);

  const result = await apiShopeeSeller.post(uri, payloadUpload, {
    ...payloadAuthRender,
    headers: {
      ...payloadAuthRender.headers,
      'Content-Type': 'multipart/form-data',
    },
  });

  return result.url_hash;
};

/**
 *
 * @param {string} conversationId
 * @param {number} shopId
 * @param {string} status
 * @param {number} bizId
 * @returns {Promise}
 */
export const updateConversationStatus = async (conversationId, shopId, status, bizId = 2) => {
  const uri = `/webchat/api/v1.2/mini/conversations/${conversationId}/status`;
  const body = {
    shop_id: shopId,
    status,
    biz_id: bizId,
  };

  const { userId, ctoken, authorization } = await readySendChat();

  validateAuth(userId, ctoken, authorization);

  const payload = buildConversationPayload(userId, ctoken, authorization);
  const result = await apiShopeeSeller.put(uri, body, payload);

  return result;
};

export const setConversationActive = async (conversationId, shopId) => {
  return updateConversationStatus(conversationId, shopId, 'activated');
};

export const setConversationClosed = async (conversationId, shopId) => {
  return updateConversationStatus(conversationId, shopId, 'closed');
};

/**
 *
 * @param {number} userId
 * @param {number} shopId
 * @param {number} bizId
 * @param {boolean} onMessageReceived
 * @param {string} entryPoint
 * @returns {Promise<ShopeeWebchatConversationRedirection>}
 */
export const getConversationRedirection = async (
  userId,
  shopId,
  bizId = 0,
  onMessageReceived = true,
  entryPoint = 'seller_contact_buyer',
) => {
  const uri = '/webchat/api/v1.2/mini/conversation/redirection';
  const body = {
    user_id: Number(userId),
    shop_id: Number(shopId),
    biz_id: Number(bizId),
    on_message_received: onMessageReceived,
    entry_point: entryPoint,
  };

  const { userId: currentUserId, ctoken, authorization } = await readySendChat();

  validateAuth(currentUserId, ctoken, authorization);

  const payload = buildConversationPayload(currentUserId, ctoken, authorization);
  const result = await apiShopeeSeller.post(uri, body, payload);

  return result;
};
