import type { Email } from "@/lib/email-data"
import type { InboxSortMode } from "@/lib/mail-settings/types"
import { isListRowRead } from "@/lib/mail-thread"

export type MailSortContext = {
  readOverrides: Record<string, boolean>
  starredIds: string[]
  importantIds: string[]
}

export type MailSortOptions = {
  conversationMode: boolean
  byId: Map<string, Email>
}

function mailTimestamp(email: Email): number {
  const t = new Date(email.date).getTime()
  return Number.isFinite(t) ? t : 0
}

function compareByDateDesc(a: Email, b: Email): number {
  return mailTimestamp(b) - mailTimestamp(a)
}

function isUnread(
  email: Email,
  ctx: MailSortContext,
  opts: MailSortOptions
): boolean {
  return !isListRowRead(
    email,
    ctx.readOverrides,
    opts.byId,
    opts.conversationMode
  )
}

function isStarred(email: Email, ctx: MailSortContext): boolean {
  const storeId = email.threadHeadId ?? email.id
  return ctx.starredIds.includes(storeId) || email.starred
}

function isImportant(email: Email, ctx: MailSortContext): boolean {
  const storeId = email.threadHeadId ?? email.id
  return ctx.importantIds.includes(storeId) || email.important
}

export function sortEmailsForInbox(
  rows: Email[],
  mode: InboxSortMode,
  ctx: MailSortContext,
  opts: MailSortOptions
): Email[] {
  const sorted = [...rows]
  if (mode === "default") {
    sorted.sort(compareByDateDesc)
    return sorted
  }

  sorted.sort((a, b) => {
    let primary = 0
    switch (mode) {
      case "important":
        primary =
          Number(isImportant(b, ctx)) - Number(isImportant(a, ctx))
        break
      case "unread":
        primary = Number(isUnread(b, ctx, opts)) - Number(isUnread(a, ctx, opts))
        break
      case "starred":
        primary = Number(isStarred(b, ctx)) - Number(isStarred(a, ctx))
        break
      default:
        break
    }
    if (primary !== 0) return primary
    return compareByDateDesc(a, b)
  })
  return sorted
}
