import { FetchState, Ticket, TicketMessage } from "@frontend/kitui";
import { create } from "zustand";
import { createJSONStorage, devtools, persist } from "zustand/middleware";
import { useUserStore } from "./user";
import { produce } from "immer";

type SessionData = {
  ticketId: string;
  sessionId: string;
};
interface AuthData {
  sessionData: SessionData | null;
  isMessageSending: boolean;
  messages: TicketMessage[];
  apiPage: number;
  messagesPerPage: number;
  lastMessageId: string | undefined;
  isPreventAutoscroll: boolean;
  unauthTicketMessageFetchState: FetchState;
}
interface TicketStore {
  unauthData: AuthData;
  authData: AuthData;
  tickets: Ticket[];
}

let params = new URLSearchParams(document.location.search);


const initAuthData = {
  sessionData: null,
  isMessageSending: false,
  messages: [],
  apiPage: 0,
  messagesPerPage: 10,
  lastMessageId: undefined,
  isPreventAutoscroll: false,
  unauthTicketMessageFetchState: "idle" as FetchState,
  tickets: []
};
const initState = {
  unauthData: initAuthData,
  authData: initAuthData,
  tickets: []
};

export const useTicketStore = create<TicketStore>()(
  persist(
    devtools((set, get) => initState, {
      name: "Unauth tickets",
    }),
    {
      version: 0,
      name: "unauth-ticket",
      storage: createJSONStorage(() => localStorage),
    },
  ),
);

export const cleanAuthTicketData = () => {
  useTicketStore.setState({ authData: initAuthData });
};

export const cleanUnauthTicketData = () => {
  useTicketStore.setState({ unauthData: initAuthData });
};

export const setTicketData = (sessionData: SessionData) =>
  updateTicket((ticket) => {
    ticket.sessionData = sessionData;
  });

export const setIsMessageSending = (
  isMessageSending: AuthData["isMessageSending"],
) =>
  updateTicket((ticket) => {
    ticket.isMessageSending = isMessageSending;
  });

export const addOrUpdateUnauthMessages = (receivedMessages: TicketMessage[]) =>
  updateTicket((ticket) => {
    const filtered = filterMessageUncompleteness(receivedMessages);
    if (filtered.length === 0) return;

    const messageIdToMessageMap: { [messageId: string]: TicketMessage } = {};

    [...ticket.messages, ...filtered].forEach(
      (message) => (messageIdToMessageMap[message.id] = message),
    );

    const sortedMessages = Object.values(messageIdToMessageMap).sort(
      sortMessagesByTime,
    );

    ticket.messages = sortedMessages;
    // if (debug) alert(sortedMessages[sortedMessages.length - 1])
    // if (debug) alert(typeof sortedMessages.at)

    // if (Array.isArray(sortedMessages)) ticket.lastMessageId = sortedMessages?.at(-1)?.id || "";
    if (Array.isArray(sortedMessages)) ticket.lastMessageId = sortedMessages?.[sortedMessages.length - 1]?.id || "";
  });

export const incrementUnauthMessage = () =>
  updateTicket((ticket) => {
    ticket.apiPage++;
  });

export const setUnauthIsPreventAutoscroll = (isPreventAutoscroll: boolean) =>
  updateTicket((ticket) => {
    ticket.isPreventAutoscroll = isPreventAutoscroll;
  });

export const setUnauthTicketMessageFetchState = (
  unauthTicketMessageFetchState: FetchState,
) =>
  updateTicket((ticket) => {
    ticket.unauthTicketMessageFetchState = unauthTicketMessageFetchState;
  });

function sortMessagesByTime(ticket1: TicketMessage, ticket2: TicketMessage) {
  const date1 = new Date(ticket1.created_at).getTime();
  const date2 = new Date(ticket2.created_at).getTime();
  return date1 - date2;
}

function filterMessageUncompleteness(messages: TicketMessage[]) {
  return messages.filter(
    (message) =>
      "id" in message &&
      "ticket_id" in message &&
      "user_id" in message &&
      "session_id" in message &&
      "message" in message &&
      "files" in message &&
      "shown" in message &&
      "request_screenshot" in message &&
      "created_at" in message &&
      ((message.files !== null && message.files.length > 0) ||
        message.message.length > 0),
  );
}

export const updateTicket = <T extends AuthData>(
  recipe: (ticket: AuthData) => void,
) =>
  setProducedState(
    (state) => {
      //В зависимости от авторизованности вызывается изменение разных объектов
      if (Boolean(useUserStore.getState().userId)) {
        recipe(state.authData);
      } else {
        recipe(state.unauthData);
      }
    },
    {
      type: "updateTicket",
      recipe,
    },
  );

function setProducedState<A extends string | { type: string }>(
  recipe: (state: TicketStore) => void,
  action?: A,
) {
  useTicketStore.setState((state) => produce(state, recipe), false, action);
}

// Функция для записи тикетов в стор
export const setTickets = (tickets: Ticket[] | null) => {
  useTicketStore.setState((state) => ({
    ...state,
    tickets: tickets || []
  }), false);
};
