import { FetchState, Ticket, TicketMessage } from "@frontend/kitui";
import { create } from "zustand";
import { devtools, persist, createJSONStorage } 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 {
  ticketCount: number;
  tickets: Ticket[];
  apiPage: number;
  ticketsPerPage: number;
  ticketsFetchState: FetchState;
  authData: AuthData;
  unauthData: AuthData;
}

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

const initialState: TicketStore = {
  ticketCount: 0,
  tickets: [],
  apiPage: 0,
  ticketsPerPage: 10,
  ticketsFetchState: "idle",
  authData: initAuthData,
  unauthData: initAuthData,
};

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

export const setTicketCount = (ticketCount: number) =>
  useTicketStore.setState({ ticketCount });

export const setTicketApiPage = (apiPage: number) =>
  useTicketStore.setState({ apiPage: apiPage });

export const updateTickets = (receivedTickets: Ticket[]) => {
  const state = useTicketStore.getState();
  const ticketIdToTicketMap: { [ticketId: string]: Ticket } = {};

  [...state.tickets, ...receivedTickets].forEach(
    (ticket) => (ticketIdToTicketMap[ticket.id] = ticket)
  );

  useTicketStore.setState({ tickets: Object.values(ticketIdToTicketMap) });
};

export const clearTickets = () => useTicketStore.setState({ ...initialState });

export const setTicketsFetchState = (ticketsFetchState: FetchState) =>
  useTicketStore.setState({ ticketsFetchState });

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

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);
}

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)
  );
}

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;
}

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;
    ticket.lastMessageId = sortedMessages.at(-1)?.id;
  });

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

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

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

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