"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<void>
  requestArchiveScheduled: (id: string) => Promise<void>
  requestSnoozeScheduled: (id: string) => Promise<void>
  requestToggleReadScheduled: (id: string, read: boolean) => Promise<void>
  requestRescheduleScheduled: (id: string, sendAtIso: string) => Promise<void>
  requestGetScheduledEditPayload: (id: string) => Promise<ScheduleSendPayload | null>
  requestUpdateScheduledSend: (id: string, payload: ScheduleSendPayload) => Promise<void>
  requestSendScheduledNow: (id: string) => Promise<void>
  requestSnoozeMailboxEmail: (row: Email) => Promise<void>
  requestRestoreSnoozedToInbox: (row: Email) => Promise<void>
}

const ScheduledMailContext = createContext<ScheduledMailContextValue | null>(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<ScheduleSendPayload | null> => {
      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<ScheduledMailContextValue>(
    () => ({
      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 (
    <ScheduledMailContext.Provider value={value}>
      {children}
    </ScheduledMailContext.Provider>
  )
}

export function useScheduledMail() {
  const ctx = useContext(ScheduledMailContext)
  if (!ctx) {
    throw new Error("useScheduledMail must be used within ScheduledMailProvider")
  }
  return ctx
}
