import { defineStore } from "pinia";
import { ref } from "vue";
import { io } from "socket.io-client";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import type {
  SupportMessageResponse,
  SupportIssueResponse,
  SupportIssueCategoryResponse,
  SupportMessageStatusResponse,
  SupportUserStatus,
  SupportMessageStatus,
} from "@/modules/00_support/interface/index/Main";
import { useCounterMixin } from "@/stores/mixin";
import { getToken, tokenParsed } from "@/plugins/auth";

export const useSupportStore = defineStore("supportServiceStore", () => {
  const { showLoader, hideLoader, messageError } = useCounterMixin();
  const openChat = ref<boolean>(false);
  const icon = ref<string>("mdi-account-check");

  const userId = ref<string | undefined>("");
  const userStatus = ref<SupportUserStatus[]>([]);
  const issue = ref<SupportIssueResponse>();
  const issueCategory = ref<SupportIssueCategoryResponse>();
  const messageStatus = ref<SupportMessageStatusResponse>();
  const message = ref<SupportMessageResponse>();
  const currentIssue = ref<string>("");
  const currentIssueDate = ref<any>("");
  const currentTitle = ref<string>("");
  const items = ref<any>([{}, {}, {}, {}, {}, {}, {}]);
  const scrollContainer = ref();

  const socket = io(config.API.supportSocket, {
    auth: { token: getToken() },
    autoConnect: false,
    path: "/api/v1/support/socket/",
  });

  socket.on("users", (data: SupportUserStatus[]) => {
    userStatus.value = data;
  });

  socket.on("online", async (r) => {
    const user = await tokenParsed();
    userId.value = user?.sub;
    userStatus.value.push({
      socketId: r.socketId,
      userId: r.userId,
      name: r.name,
      role: r.role,
    });
  });

  socket.on("offline", (socketId: string) => {
    if (socketId === socket.id) return;
    userStatus.value = userStatus.value.filter((v) => v.socketId !== socketId);
  });

  socket.on("notify-message", (r) => {
    if (issue.value) {
      issue.value.result = issue.value.result.map((v) => {
        if (v.id === r.issueId) {
          v.unreadCount++;
          v.lastMessage = r.content;
        }
        if (currentIssue.value === r.issueId) {
          v.unreadCount = 0;
        }
        return v;
      });
    }
  });

  socket.on("message", (r) => {
    message.value?.result.message.push(r);

    if (issue.value) {
      issue.value.result = issue.value.result.map((v) => {
        if (v.id === r.issueId) v.lastMessage = r.content;
        return v;
      });
    }
    socket.emit("mark-read", { issueId: currentIssue.value });
    scrollToEnd();
  });

  socket.on("read", (r) => {
    if (messageStatus.value) {
      messageStatus.value.result = messageStatus.value.result.map((v) => {
        if (v.fromUserId === r.fromUserId) return r;
        return v;
      });
    }
  });

  function scrollToEnd(position: Number = 1) {
    setTimeout(() => {
      scrollContainer.value?.setScrollPercentage("vertical", position);
    }, 150);
  }

  function sendMessage(content: string, to: string) {
    if (content.trim() !== "") {
      socket.emit("message", { to, content });
      scrollToEnd();
    }
  }

  async function fetchMessageStatus(issueId: string) {
    showLoader();
    const res = await http
      .get(config.API.supportMessageStatus(issueId))
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        hideLoader();
      });
    if (res && res.data) {
      messageStatus.value = res.data;
    }
  }

  async function fetchMessage(issueId: string) {
    showLoader();
    const res = await http
      .get(config.API.supportMessage(issueId))
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        hideLoader();
      });
    if (res && res.data) {
      message.value = await res.data;
      message.value?.result.message.reverse();
      socket.emit("join-issue", { issueId });
      socket.emit("mark-read", { issueId });
      scrollToEnd();
    }
  }

  async function fetchIssue() {
    if (!userId.value) return;
    showLoader();
    const res = await http
      .get(config.API.supportIssueUserId(userId.value))
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        hideLoader();
      });

    if (res && res.data) {
      issue.value = res.data;
    }
  }

  async function fetchIssueCategory() {
    showLoader();

    const res = await http
      .get(config.API.supportIssueCategory)
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        hideLoader();
      });

    if (res && res.data) {
      issueCategory.value = res.data;
    }
  }

  async function newIssue(title: string, categoryId: string) {
    showLoader();

    const requestBody = {
      title: title,
      categoryId: categoryId,
    };

    const res = await http
      .post(config.API.supportNewIssue, requestBody)
      .catch((err) => {
        console.log(err);
      })
      .finally(() => {
        hideLoader();
      });

    if (res) {
      fetchIssue();
    }
  }

  async function searchIssue(searchData: string) {
    const res = await http
      .get(config.API.supportSearchIssue(searchData))
      .catch((err) => {
        console.log(err);
      });
    if (res && res.data) {
      issue.value = res.data;
    }
  }

  return {
    userId,
    issue,
    issueCategory,
    message,
    messageStatus,
    userStatus,
    currentIssue,
    currentIssueDate,
    currentTitle,
    fetchIssue,
    fetchIssueCategory,
    fetchMessageStatus,
    fetchMessage,
    sendMessage,
    newIssue,
    searchIssue,
    openChat,
    items,
    socket,
    scrollContainer,
    icon,
  };
});
