import axios from "axios";
import parsePhoneNumber from "libphonenumber-js";
import { all, call, put, select, takeLatest } from "redux-saga/effects";
import { logImEXEvent } from "../../firebase/firebase.utils";
import {
  CONVERSATION_ID_BY_PHONE,
  CREATE_CONVERSATION,
  TOGGLE_CONVERSATION_ARCHIVE
} from "../../graphql/conversations.queries";
import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
import client from "../../utils/GraphQLClient";
import { selectBodyshop } from "../user/user.selectors";
import { sendMessageFailure, sendMessageSuccess, setSelectedConversation } from "./messaging.actions";
import MessagingActionTypes from "./messaging.types";

export function* onToggleChatVisible() {
  yield takeLatest(MessagingActionTypes.TOGGLE_CHAT_VISIBLE, toggleChatLogging);
}

export function* toggleChatLogging() {
  try {
    yield logImEXEvent("messaging_toggle_popup");
  } catch (error) {
    console.log("Error in sendMessage saga.", error);
  }
}

export function* onOpenChatByPhone() {
  yield takeLatest(MessagingActionTypes.OPEN_CHAT_BY_PHONE, openChatByPhone);
}

export function* openChatByPhone({ payload }) {
  logImEXEvent("messaging_open_by_phone");
  const { socket, phone_num, jobid } = payload;
  if (!socket || !phone_num) return;

  const p = parsePhoneNumber(phone_num, "CA");
  const bodyshop = yield select(selectBodyshop);

  try {
    // Fetch conversations including archived ones
    const {
      data: { conversations }
    } = yield client.query({
      query: CONVERSATION_ID_BY_PHONE,
      variables: { phone: p.number },
      fetchPolicy: "no-cache" // Ensure the query always gets the latest data
    });

    // Sort conversations by `updated_at` or `created_at` and pick the last one for the given phone number
    const sortedConversations = conversations
      ?.filter((c) => c.phone_num === p.number) // Filter to match the phone number
      .sort((a, b) => new Date(a.created_at) - new Date(b.created_at)); // Sort by `updated_at`

    const existingConversation = sortedConversations?.[sortedConversations.length - 1] || null;

    if (existingConversation) {
      let updatedConversation = existingConversation;

      if (existingConversation.archived) {
        // If the conversation is archived, unarchive it
        const {
          data: { update_conversations_by_pk: unarchivedConversation }
        } = yield client.mutate({
          mutation: TOGGLE_CONVERSATION_ARCHIVE,
          variables: {
            id: existingConversation.id,
            archived: false
          }
        });

        updatedConversation = unarchivedConversation;

        // Emit an event indicating the conversation was unarchived
        socket.emit("conversation-modified", {
          type: "conversation-unarchived",
          conversationId: unarchivedConversation.id,
          bodyshopId: bodyshop.id,
          archived: false
        });
      }

      // Set the unarchived or already active conversation as selected
      yield put(setSelectedConversation(updatedConversation.id));

      // Add job tag if needed
      if (jobid && !updatedConversation.job_conversations.find((jc) => jc.jobid === jobid)) {
        yield client.mutate({
          mutation: INSERT_CONVERSATION_TAG,
          variables: {
            conversationId: updatedConversation.id,
            jobId: jobid
          }
        });
      }
    } else {
      // No conversation exists, create a new one
      const {
        data: {
          insert_conversations: { returning: newConversations }
        }
      } = yield client.mutate({
        mutation: CREATE_CONVERSATION,
        variables: {
          conversation: [
            {
              phone_num: p.number,
              bodyshopid: bodyshop.id,
              job_conversations: jobid ? { data: { jobid: jobid } } : null
            }
          ]
        }
      });

      const createdConversation = newConversations[0];

      // Emit event for the new conversation with full details
      socket.emit("conversation-modified", {
        bodyshopId: bodyshop.id,
        type: "conversation-created",
        ...createdConversation
      });

      // Set the newly created conversation as selected
      yield put(setSelectedConversation(createdConversation.id));
    }
  } catch (error) {
    console.error("Error in openChatByPhone saga.", error);
  }
}

export function* onSendMessage() {
  yield takeLatest(MessagingActionTypes.SEND_MESSAGE, sendMessage);
}

export function* sendMessage({ payload }) {
  try {
    const response = yield call(axios.post, "/sms/send", payload);
    if (response.status === 200) {
      yield put(sendMessageSuccess(payload));
    } else {
      yield put(sendMessageFailure(response.data));
    }
  } catch (error) {
    console.log("Error in sendMessage saga.", error);
    yield put(sendMessageFailure(error));
  }
}

export function* messagingSagas() {
  yield all([call(onSendMessage), call(onOpenChatByPhone), call(onToggleChatVisible)]);
}
