import fs from 'node:fs/promises'

import { ntfyMessagePriorityDefault } from './priorities.js'
import type { FetchHeaders, NtfyMessageOptions } from './types.js'

/**
 * The default ntfy server to use.
 */
export const DEFAULT_NTFY_SERVER = 'https://ntfy.sh'

/**
 * The default priority to use when sending a message.
 */
export const DEFAULT_NTFY_PRIORITY = ntfyMessagePriorityDefault

/**
 * @deprecated Use `DEFAULT_NTFY_PRIORITY` instead.
 */
export const DEFAULT_PRIORITY = DEFAULT_NTFY_PRIORITY

/**
 * Send a message through an ntfy server.
 * @param ntfyMessage The message to post.
 * @returns `true` if the message was posted.
 */
export default async function publish(
  ntfyMessage: NtfyMessageOptions
): Promise<boolean> {
  /*
   * Set Server
   */

  let server = ntfyMessage.server ?? DEFAULT_NTFY_SERVER

  if (!server.endsWith('/')) {
    server += '/'
  }

  /*
   * Build Headers
   */

  const messageHeaders: FetchHeaders = {
    Priority: ntfyMessage.priority ?? DEFAULT_NTFY_PRIORITY
  }

  if (ntfyMessage.title !== undefined) {
    messageHeaders.Title = ntfyMessage.title
  }

  if (ntfyMessage.tags !== undefined) {
    messageHeaders.Tags = ntfyMessage.tags.join(',')
  }

  if (ntfyMessage.clickURL !== undefined) {
    messageHeaders.Click = ntfyMessage.clickURL
  }

  if (ntfyMessage.iconURL !== undefined) {
    messageHeaders.Icon = ntfyMessage.iconURL
  }

  // Attachments

  let hasLocalAttachment = false

  if (ntfyMessage.fileAttachmentURL !== undefined) {
    hasLocalAttachment = !(
      ntfyMessage.fileAttachmentURL.toLowerCase().startsWith('http://') ||
      ntfyMessage.fileAttachmentURL.toLowerCase().startsWith('https://')
    )

    if (!hasLocalAttachment) {
      messageHeaders.Attach = ntfyMessage.fileAttachmentURL
    }
  }

  const fileData = hasLocalAttachment
    ? // eslint-disable-next-line security/detect-non-literal-fs-filename
      await fs.readFile(ntfyMessage.fileAttachmentURL as string)
    : undefined

  if (ntfyMessage.fileName !== undefined) {
    messageHeaders.Filename = ntfyMessage.fileName
  }

  // Cache

  if (Object.hasOwn(ntfyMessage, 'cache') && !(ntfyMessage.cache ?? true)) {
    messageHeaders.Cache = 'no'
  }

  /*
   * Send Message
   */

  const response = await fetch(server + ntfyMessage.topic, {
    method: 'POST',
    body: hasLocalAttachment ? fileData : ntfyMessage.message ?? '',
    headers: messageHeaders as Record<string, string>
  })

  return response.ok
}

export { isSupportedTagEmoji, ntfyTagEmojis } from './emoji.js'

export {
  ntfyMessagePrioritiesDefault,
  ntfyMessagePrioritiesHigh,
  ntfyMessagePrioritiesLow,
  ntfyMessagePrioritiesMax,
  ntfyMessagePrioritiesMin,
  ntfyMessagePriorityDefault,
  ntfyMessagePriorityHigh,
  ntfyMessagePriorityLow,
  ntfyMessagePriorityMax,
  ntfyMessagePriorityMin
} from './priorities.js'

export type {
  FetchHeaders,
  NtfyMessageOptions,
  NtfyMessagePriority
} from './types.js'
