<script setup lang="ts">
import { CometChat, Group, GroupMember } from "@cometchat/chat-sdk-javascript";
import { CometChatMessageEvents, MessageStatus } from "@cometchat/uikit-resources";
import {
  PropType,
  Ref,
  onBeforeUnmount,
  onMounted,
  onUnmounted,
  provide,
  ref,
  watch,
  watchEffect,
} from "vue";
import chat from "../chat";
import { connect, disconnect } from "../chat/connection";
import { getGroupMembersInfo } from "../chat/data";
import logger from "../chat/logger";
import { loggedIn } from "../chat/login";
import { watchAndApplyStyle } from "../chat/styleFix";
import { ChatInstance, ParticipantInfo } from "../chat/types";
import { offlineStore } from "../offline";
import { onlineMode, onlineStatus } from "../offline/connectivity";
import BccChatMessages from "./BccChatMessages.vue";
import BccScheduledMessages from "./BccScheduledMessages.vue";
const props = defineProps({
  chatUid: { type: String, required: true },
  senderDisplayName: { type: String, required: false },
  hideDeletedMessages: { type: Boolean, required: false, default: false },
  groupMessageGetter: {
    type: Function as PropType<(guid: string, query: string) => Promise<any>>,
    required: false,
  },
  loadMessageId: { type: String, required: false, default: "" },
});

const componentId = ref(
  `component-${Math.random().toString(36).substring(2, 11)}`
);
const chatGroup = ref<Group>();
const chatGroupNotFound = ref(false);

const isChatMessagesEmpty = ref(false);

const emit = defineEmits(['groupMembersFetched']);
const groupMembers = ref<ParticipantInfo[]>();

const chatInstance: Ref<ChatInstance> = ref({
  componentId: componentId,
  replyToMessage: null,
  captionedAttachment: null,
  decoyAttachment: null,
  showScheduledMessagesChat: false,
  showAlert: false,
  showRescheduleAlert: false,
  userInput: null,
  rescheduleInfo: null
});

provide("chatInstance", chatInstance);

const localLoadMessageId = ref(props.loadMessageId);
watch(() => props.loadMessageId, (newVal) => {
  localLoadMessageId.value = newVal;
});

const onMessageSend = CometChatMessageEvents.ccMessageSent.subscribe(({ message, status }) => {
  if (status !== MessageStatus.inprogress) {
    return
  }

  let metadata: any = (message as any)?.getMetadata() || {};
  let scope: string | undefined = chatGroup.value?.getScope();

  if (chatInstance.value.replyToMessage) {
    metadata.replyToMessageId = chatInstance.value.replyToMessage?.getId();
    chatInstance.value.replyToMessage = null;
  }

  if (props.senderDisplayName && scope == "moderator") {
    metadata.senderDisplayName = props.senderDisplayName
  }

  const muid = window.crypto.randomUUID();
  message.setMuid(muid);
  const tags = (message as any).getTags() ?? [];
  tags.push(muid);
  (message as any).setTags(tags);
  (message as any).setMetadata(metadata);
});

watch([loggedIn, chat.onlineStatus, () => props.chatUid, chat.initialized, () => props.groupMessageGetter, chat.scrollToMessageId, localLoadMessageId], async ([_loggedIn, _online, _chatUid, _initialized, _groupMessageGetter, _scrollToMessageId, _localLoadMessageId]) => {
  logger.debug("ChatMessageList watch changed", { chatUid: _chatUid, loggedIn: _loggedIn, online: _online, initialized: _initialized });
  try {
    if (_loggedIn && _chatUid && _initialized) {
      chatGroupNotFound.value = false;
      const [_, group] = await Promise.all([
        connect(componentId.value),
        chat.getGroup(props.chatUid)
      ])
      chatGroup.value = group ?? undefined;
      chatGroupNotFound.value = group === undefined;

      if (_groupMessageGetter && !chatGroup.value?.getHasJoined()) {
        chat.updateGetGroupMessages(_groupMessageGetter)
      }

      if (_scrollToMessageId) {
        chat.scrollToMessage(_scrollToMessageId);
      }

      if (_localLoadMessageId) {
        chat.loadMessageId.value = _localLoadMessageId;
        localLoadMessageId.value = "";
      }

      isChatMessagesEmpty.value = false;

      if (chatGroup.value) {

        let isChannel = (chatGroup.value.getMetadata() as any).isChannel;

        watchAndApplyStyle(".bcc-chat-message-list-wrapper", [
          {
            selector: ".cc-messagebubble-wrapper__container",
            style: {
              "max-width": isChannel ? "95%" : "80%"
            }
          }
        ])

        // Allow some time for messages to load before displaying "no messages"
        setTimeout(() => {
          if (offlineStore.getGroupMessages(_chatUid, {
            per_page: 1,
            affix: 'prepend'
          }).total === 0) {
            isChatMessagesEmpty.value = true;
          } else {
            isChatMessagesEmpty.value = false;
          }
        }, 1500);

        if (!isChannel) {
          getGroupMembersInfo(_chatUid).then((participants) => groupMembers.value = participants);
        } else {
          groupMembers.value = [];
        }
      }
      await chat.clearGroupChatCount(props.chatUid);
    } else if (chatGroup.value) {
      chatGroup.value = undefined;
    }
  } catch (error) {
    logger.error("Error in ChatMessageList watch", { error, chatUid: _chatUid, loggedIn: _loggedIn, online: _online, initialized: _initialized });
  }
}, { immediate: true });

watchEffect(() => {
  if (groupMembers.value && groupMembers.value.length) {
    emit('groupMembersFetched', groupMembers.value);
  } else {
    emit('groupMembersFetched', []);
  }
})

onMounted(() => {
  logger.debug("Mounting chat", { chatUid: props.chatUid });
  setTimeout(() => {
    if (!chatGroup.value && !chatGroupNotFound.value) {
      logger.error("Chat not loaded after 5 seconds", { chatUid: props.chatUid, connected: chat.connected.value, loggedIn: loggedIn.value, onlineMode: onlineMode.value, onlineStatus: onlineStatus.value, initialized: chat.initialized.value });
    } else {
      logger.debug("Chat successfully loaded", { chatUid: props.chatUid, connected: chat.connected.value, loggedIn: loggedIn.value, onlineMode: onlineMode.value, onlineStatus: onlineStatus.value, initialized: chat.initialized.value });
    }
  }, 5000);
  watchAndApplyStyle(".bcc-chat-message-list-wrapper", [
    {
      selector: ".cc__text",
      style: { color: "var(--cc__text-color)" },
      shadowDomSelector: "cometchat-text-bubble",
    },
    {
      selector: ".cc__preview__subtitle",
      style: {
        "overflow": "hidden",
        "display": "-webkit-box",
        "-webkit-box-orient": "vertical",
        "-webkit-line-clamp": "1",
        "word-break": "break-all"
      },
      shadowDomSelector: "cometchat-preview",
    },
    {
      selector: ".cc__polldata",
      style: { color: "var(--cc__primary150)" },
      shadowDomSelector: "create-poll"
    },
    {
      selector: ".cc__pollsbubble__option",
      style: {
        backgroundColor: "var(--cc__background)",
      },
      shadowDomSelector: "polls-bubble"
    },
  ]);


  CometChat.addGroupListener("groupListener", new CometChat.GroupListener({
    onGroupMemberScopeChanged: (_action: any, changedUser: GroupMember, newScope: any, _oldScope: any, _changedGroup: GroupMember) => {
      handleGroupMemberChanges(changedUser, "update", newScope);
    },
    onGroupMemberKicked: (_action: any, changedUser: GroupMember, _Ye: any, _group: any) => {
      handleGroupMemberChanges(changedUser, "remove");
    },
    onGroupMemberBanned: (_action: any, user: GroupMember, _Ye: any, _group: any) => {
      handleGroupMemberChanges(user, "remove");
    },
    onGroupMemberUnbanned: (_action: any, user: GroupMember, _Ye: any, _group: any) => {
      handleGroupMemberChanges(user, "add");
    },
    onMemberAddedToGroup: (_action: any, user: GroupMember, _Ye: any, _group: any) => {
      handleGroupMemberChanges(user, "add");
    },
    onGroupMemberLeft: (_action: any, user: GroupMember, _group: any) => {
      handleGroupMemberChanges(user, "remove");
    },
    onGroupMemberJoined: (_action: any, user: GroupMember, _group: any) => {
      handleGroupMemberChanges(user, "add");
    }
  }))
});

onBeforeUnmount(() => {
  onMessageSend.unsubscribe();
})

onUnmounted(async () => {
  await disconnect(componentId.value);
});

function handleGroupMemberChanges(changedUser: GroupMember, action: string, newScope?: string) {
  let participant: ParticipantInfo = {
    uid: changedUser.getUid(),
    displayName: changedUser.getName(),
    avatar: changedUser.getAvatar(),
    role: newScope ? newScope : CometChat.GROUP_MEMBER_SCOPE.PARTICIPANT
  }

  if (action === "add" && !existsInGroup(changedUser.getUid())) {
    groupMembers.value?.push(participant)
  }

  if (action === "remove" && existsInGroup(changedUser.getUid())) {
    groupMembers.value = groupMembers.value?.filter(participant => participant.uid !== changedUser.getUid());
  }

  if (action === "update" && existsInGroup(changedUser.getUid())) {
    groupMembers.value = groupMembers.value?.map(p => p.uid === changedUser.getUid() ? { ...p, ...participant } : p);
  }
}

function existsInGroup(uid: string): boolean {
  return groupMembers.value?.some(p => p.uid === uid) ?? false;
}

function closeScheduledMessage() {
  chatInstance.value.captionedAttachment = null
  chatInstance.value.replyToMessage = null
  chatInstance.value.scheduledMessageChat = undefined
  chatInstance.value.showScheduledMessagesChat = false;
}

</script>

<template>
  <div class="bcc-chat-message-list-wrapper" :class="componentId">
    <BccChatMessages v-if="chatGroup && !chatInstance.showScheduledMessagesChat" :chatGroup="chatGroup"
      :hide-deleted-messages="props.hideDeletedMessages" :chatUid="props.chatUid"></BccChatMessages>
    <BccScheduledMessages v-else-if="chatGroup && chatInstance.showScheduledMessagesChat"
      class="bcc-scheduled-message-list" :chatGroup="chatInstance.scheduledMessageChat!"
      :originalChatUid="props.chatUid" @close="closeScheduledMessage()"></BccScheduledMessages>
    <div v-else-if="chat.onlineStatus.value === 'offline'" class="bcc-chat-message-list-offline">
      <span>Waiting for network...</span>
    </div>
    <div v-else-if="!chat.connected.value" class="bcc-chat-message-list-offline">
      <span>Connecting...</span>
    </div>
    <div v-else-if="chatGroupNotFound" class="bcc-chat-message-list-offline">
      <span>Chat not found...</span>
    </div>
    <div v-else-if="!chatGroup" class="bcc-chat-message-list-offline">
      <span>Loading chat...</span>
    </div>
    <div v-else class="bcc-chat-message-list-offline">
      <span>Loading...</span>
    </div>
    <div v-if="isChatMessagesEmpty && chatGroup" class="bcc-chat-message-list-offline pointer-events-none">
      <span>No messages have been sent yet</span>
    </div>
  </div>
</template>

<style lang="scss">
.bcc-chat-message-list-wrapper {
  position: relative;
  height: 100%;
}

/*
primary: my bubble
accent: message bar text
accent100: message bar and widget buttons bg, others bubble
accent200: horizontal line on message bar
accent500: icons on message bar
accent600: dates and date separator and popup icons
accent700: avatar background, widget buttons text
accent900: text in avatar
*/

.bcc-chat-message-list {
  --cc__primary: #cfeac8;
  --cc__primary150: #004e48;
  --cc__background: #f3faf7;
  --cc__secondary: white;
  --cc__accent: #004e48;
  --cc__accent50: rgba(62, 142, 117, 0.04);
  --cc__accent100: #ffffff;
  --cc__accent200: rgba(62, 142, 117, 0.15);
  --cc__accent300: rgba(62, 142, 117, 0.24);
  --cc__accent400: rgba(62, 142, 117, 0.33);
  --cc__accent500: rgba(62, 142, 117, 0.46);
  --cc__accent600: #004e48;
  --cc__accent700: #254a40;
  --cc__accent800: rgba(62, 142, 117, 0.82);
  --cc__accent900: #f3faf7;
  --cc__text-color: #000;
  --cc__link-color: #57639e;
}

:root.dark .bcc-chat-message-list {
  --cc__primary: #57639e;
  --cc__primary150: #57639e;
  --cc__background: hsl(230, 25%, 15%);
  --cc__secondary: #111827;
  --cc__accent: #758abc;
  --cc__accent50: rgba(98, 116, 174, 0.24);
  --cc__accent100: linear-gradient(45deg, #05070b 0%, #0c111c 100%);
  --cc__accent200: rgba(98, 116, 174, 0.35);
  --cc__accent300: rgba(98, 116, 174, 0.44);
  --cc__accent400: rgba(98, 116, 174, 0.53);
  --cc__accent500: rgba(98, 116, 174, 0.66);
  --cc__accent600: #758abc;
  --cc__accent700: #6274ae;
  --cc__accent800: rgba(98, 116, 174, 0.92);
  --cc__accent900: #090A0B;
  --cc__text-color: #fff;
  --cc__link-color: #cfeac8;
}

.bcc-chat-message-list {
  height: 100%;

  /* 1. Wrapper for Messages component */
  .cc-messages-wrapper {

    /* 1.1 Messages component */
    .cc-messages-wrapper__messages {

      /* 1.1.1 Wrapper for Messages List */
      .cc-messages-wrapper__messages-list {
        height: 100%;
      }

      /* 1.1.2 Wrapper for Messages Composer */
      .cc-messagecomposer-wrapper {
        //padding: 0; //Use to remove side padding on composer
      }

      /* 1.1.3 Wrapper for Messages Composer Header View */
      .cc-messagecomposer-wrapper__headerview {
        max-height: 100%;
        margin-bottom: 5px;
      }
    }

    .cc-messagebubble-wrapper__content {
      max-width: 100%;
    }

    .cc-messagebubble-wrapper__content>div>.bcc-message-wrapper.has-text.has-image+div>div>div:not([class]) {
      justify-content: flex-end !important;
      padding: 0px 8px 8px !important;
      margin-top: -5px !important;
      height: unset !important;
      border-radius: unset !important;
      line-height: unset !important;
      position: unset !important;
      margin-right: unset !important;
      background: unset !important;
    }
  }

  .cc-messagebubble-wrapper__container {
    max-width: 80%;
  }

  .cc-messagebubble-wrapper__messageoptions {
    border-radius: 8px;

    .cc-context-menu__top-menu {
      border: 1px var(--cc__secondary) solid !important;
    }
  }


  /* 2. Message for Messages Composer when offline */
  .bcc-chat-message-composer-offline {
    position: relative;
    bottom: 38px;
    text-align: center;
    //height: 96px;
    width: 100%;
    //backdrop-filter: blur(4px);
    font: 500 11px sans-serif;

    /* 2.1 Text of Messages Composer offline view */
    span {
      width: 150px;
      display: inline;
      padding: 4px 6px;
      color: var(--cc__text-color);
      background: var(--cc__primary);
      border-radius: 8px;
    }
  }

  /* Hide send button when offline */
  &.offline .messageinput__primaryactions,
  &.offline .messageinput__auxiliaryactions,
  &.offline .messageinput__secondaryactions {
    opacity: 0.2;
  }

}

.bcc-chat-message-list-offline {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  font: 700 22px sans-serif;
  color: #bcbcbc;
}

.cc-messagecomposer__emojikeyboard {
  display: none;
}

// Hide emoji keyboard
.cc-messagecomposer__emojikeyboard {
  display: none;
}

.cc-threadedmessages-wrapper__bubbleview::-webkit-scrollbar,
.cc__message-list::-webkit-scrollbar {
  background: transparent;
  width: 8px;
}

.cc-threadedmessages-wrapper__bubbleview::-webkit-scrollbar-thumb,
.cc__message-list::-webkit-scrollbar-thumb {
  background: rgb(232, 229, 229);
  border-radius: 8px;
}
</style>