"use client"

import { create } from "zustand"
import type {
  ApiMessageFull,
  MessageSearchFilter,
  PaginatedResponse,
  ApiMessageSummary,
} from "@/lib/api/types"
import {
  createInitialDemoMessages,
  demoSentMessageFromPayload,
  listDemoMessages,
  moveDemoMessageToTrash,
  searchDemoMessages,
} from "@/lib/demo/demo-mail-api-data"
import type { SendMessagePayload } from "@/lib/api/hooks/use-compose-mutations"

type DemoMailStoreState = {
  messages: ApiMessageFull[]
  version: number
}

type DemoMailStoreActions = {
  reset: () => void
  listMessages: (
    folder: string,
    page: number,
    pageSize: number
  ) => PaginatedResponse<ApiMessageSummary>
  searchMessages: (
    filter: MessageSearchFilter | null,
    page?: number,
    pageSize?: number
  ) => PaginatedResponse<ApiMessageSummary>
  getMessage: (id: string) => ApiMessageFull | undefined
  getThread: (threadId: string) => ApiMessageFull[]
  updateFlags: (id: string, flags: string[]) => ApiMessageFull | undefined
  updateLabels: (id: string, labels: string[]) => ApiMessageFull | undefined
  deleteMessage: (id: string) => ApiMessageFull | undefined
  sendMessage: (payload: SendMessagePayload) => ApiMessageFull
  bump: () => void
}

function withMessages(
  messages: ApiMessageFull[],
  id: string,
  patch: (message: ApiMessageFull) => ApiMessageFull
): ApiMessageFull[] {
  return messages.map((message) => (message.id === id ? patch(message) : message))
}

export const useDemoMailStore = create<DemoMailStoreState & DemoMailStoreActions>(
  (set, get) => ({
    messages: createInitialDemoMessages(),
    version: 0,

    reset: () =>
      set({
        messages: createInitialDemoMessages(),
        version: get().version + 1,
      }),

    bump: () => set({ version: get().version + 1 }),

    listMessages: (folder, page, pageSize) =>
      listDemoMessages(get().messages, folder, page, pageSize),

    searchMessages: (filter, page, pageSize) =>
      searchDemoMessages(get().messages, filter, page, pageSize),

    getMessage: (id) => get().messages.find((message) => message.id === id),

    getThread: (threadId) => {
      const message = get().messages.find(
        (entry) => entry.thread_id === threadId || entry.id === threadId
      )
      return message ? [message] : []
    },

    updateFlags: (id, flags) => {
      let updated: ApiMessageFull | undefined
      set((state) => ({
        messages: withMessages(state.messages, id, (message) => {
          updated = { ...message, flags }
          return updated
        }),
        version: state.version + 1,
      }))
      return updated
    },

    updateLabels: (id, labels) => {
      let updated: ApiMessageFull | undefined
      set((state) => ({
        messages: withMessages(state.messages, id, (message) => {
          updated = { ...message, labels }
          return updated
        }),
        version: state.version + 1,
      }))
      return updated
    },

    deleteMessage: (id) => {
      let updated: ApiMessageFull | undefined
      set((state) => ({
        messages: withMessages(state.messages, id, (message) => {
          updated = moveDemoMessageToTrash(message)
          return updated
        }),
        version: state.version + 1,
      }))
      return updated
    },

    sendMessage: (payload) => {
      const created = demoSentMessageFromPayload(payload)
      set((state) => ({
        messages: [created, ...state.messages],
        version: state.version + 1,
      }))
      return created
    },
  })
)
