"use client" import { createContext, useContext, useMemo, useCallback, type ReactNode, } from "react" import type { Email } from "@/lib/email-data" import type { ScheduleSendPayload } from "@/lib/api/scheduled-mail" import { useScheduledStore, type OutboxEntry, } from "@/lib/stores/scheduled-store" import { useScheduleSend, useRescheduleSend, useCancelScheduled, useSendNow, } from "@/lib/api/hooks/use-compose-mutations" import { useActiveAccount } from "@/lib/stores/account-store" export type { ScheduleSendPayload } from "@/lib/api/scheduled-mail" type ScheduledMailContextValue = { scheduledEmails: OutboxEntry[] snoozedEmails: Email[] scheduleSend: (payload: ScheduleSendPayload) => Promise<{ id: string }> removeScheduledLocal: (id: string) => void requestDeleteScheduled: (id: string) => Promise requestArchiveScheduled: (id: string) => Promise requestSnoozeScheduled: (id: string) => Promise requestToggleReadScheduled: (id: string, read: boolean) => Promise requestRescheduleScheduled: (id: string, sendAtIso: string) => Promise requestGetScheduledEditPayload: (id: string) => Promise requestUpdateScheduledSend: (id: string, payload: ScheduleSendPayload) => Promise requestSendScheduledNow: (id: string) => Promise requestSnoozeMailboxEmail: (row: Email) => Promise requestRestoreSnoozedToInbox: (row: Email) => Promise } const ScheduledMailContext = createContext(null) export function ScheduledMailProvider({ children }: { children: ReactNode }) { const scheduledEmails = useScheduledStore((s) => s.scheduledEmails) const snoozedEmails = useScheduledStore((s) => s.snoozedEmails) const account = useActiveAccount() const scheduleSendMutation = useScheduleSend() const rescheduleMutation = useRescheduleSend() const cancelMutation = useCancelScheduled() const sendNowMutation = useSendNow() const scheduleSend = useCallback( async (payload: ScheduleSendPayload): Promise<{ id: string }> => { const accountId = account?.id ?? "" const result = await scheduleSendMutation.mutateAsync({ account_id: accountId, to: payload.to.map((r) => ({ name: r.name, address: r.email })), subject: payload.subject, body_html: payload.bodyHtml, idempotency_key: `sched-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, scheduled_at: payload.sendAtIso, }) const id = result?.id ?? `local-${Date.now()}` const entry: OutboxEntry = { id, account_id: accountId, status: "scheduled", subject: payload.subject, to: payload.to.map((r) => ({ name: r.name, address: r.email })), scheduled_at: payload.sendAtIso, created_at: new Date().toISOString(), } useScheduledStore.getState().addScheduledEmail(entry) return { id } }, [scheduleSendMutation, account?.id] ) const removeScheduledLocal = useCallback((id: string) => { useScheduledStore.getState().removeScheduled(id) }, []) const requestDeleteScheduled = useCallback( async (id: string) => { await cancelMutation.mutateAsync({ id }) useScheduledStore.getState().removeScheduled(id) }, [cancelMutation] ) const requestArchiveScheduled = useCallback( async (id: string) => { await cancelMutation.mutateAsync({ id }) useScheduledStore.getState().removeScheduled(id) }, [cancelMutation] ) const requestSnoozeScheduled = useCallback( async (id: string) => { await cancelMutation.mutateAsync({ id }) useScheduledStore.getState().removeScheduled(id) }, [cancelMutation] ) const requestToggleReadScheduled = useCallback( async (_id: string, _read: boolean) => {}, [] ) const requestRescheduleScheduled = useCallback( async (id: string, sendAtIso: string) => { await rescheduleMutation.mutateAsync({ id, scheduled_at: sendAtIso }) const store = useScheduledStore.getState() const existing = store.scheduledEmails.find((e) => e.id === id) if (existing) { store.addScheduledEmail({ ...existing, scheduled_at: sendAtIso }) } }, [rescheduleMutation] ) const requestGetScheduledEditPayload = useCallback( async (id: string): Promise => { const entry = useScheduledStore.getState().scheduledEmails.find((e) => e.id === id) if (!entry) return null return { sendAtIso: entry.scheduled_at ?? new Date().toISOString(), to: entry.to.map((r) => ({ name: r.name, email: r.address })), subject: entry.subject, previewText: "", bodyHtml: "", } }, [] ) const requestUpdateScheduledSend = useCallback( async (id: string, payload: ScheduleSendPayload) => { await rescheduleMutation.mutateAsync({ id, scheduled_at: payload.sendAtIso }) const entry: OutboxEntry = { id, account_id: account?.id ?? "", status: "scheduled", subject: payload.subject, to: payload.to.map((r) => ({ name: r.name, address: r.email })), scheduled_at: payload.sendAtIso, created_at: new Date().toISOString(), } useScheduledStore.getState().addScheduledEmail(entry) }, [rescheduleMutation, account?.id] ) const requestSendScheduledNow = useCallback( async (id: string) => { await sendNowMutation.mutateAsync({ id }) useScheduledStore.getState().removeScheduled(id) }, [sendNowMutation] ) const requestSnoozeMailboxEmail = useCallback(async (row: Email) => { useScheduledStore.getState().snoozeMailboxEmail(row) }, []) const requestRestoreSnoozedToInbox = useCallback(async (row: Email) => { useScheduledStore.getState().restoreSnoozedToInbox(row) }, []) const value = useMemo( () => ({ scheduledEmails, snoozedEmails, scheduleSend, removeScheduledLocal, requestDeleteScheduled, requestArchiveScheduled, requestSnoozeScheduled, requestToggleReadScheduled, requestRescheduleScheduled, requestGetScheduledEditPayload, requestUpdateScheduledSend, requestSendScheduledNow, requestSnoozeMailboxEmail, requestRestoreSnoozedToInbox, }), [ scheduledEmails, snoozedEmails, scheduleSend, removeScheduledLocal, requestDeleteScheduled, requestArchiveScheduled, requestSnoozeScheduled, requestToggleReadScheduled, requestRescheduleScheduled, requestGetScheduledEditPayload, requestUpdateScheduledSend, requestSendScheduledNow, requestSnoozeMailboxEmail, requestRestoreSnoozedToInbox, ] ) return ( {children} ) } export function useScheduledMail() { const ctx = useContext(ScheduledMailContext) if (!ctx) { throw new Error("useScheduledMail must be used within ScheduledMailProvider") } return ctx }