import { logWarn } from '../../utils/logger.js'
import type { JsonObject } from '../../types/json.js'
import {
  getNotificationConfig,
  listEnabledBarkRecipients,
  listEnabledWpushRecipients,
} from './config-service.js'
import { sendBarkNotification } from './bark-service.js'
import { sendWpushNotification } from './wpush-service.js'

type NotificationResult = ReturnType<typeof mapNotificationResult>
type NotificationInput = {
  title?: string
  body?: string
  category?: string
  url?: string
}

export async function sendInternalNotification(input: NotificationInput = {}) {
  const config = getNotificationConfig()
  const bark = (config.channels?.bark || {}) as { serverUrl?: string }
  const barkRecipients = listEnabledBarkRecipients(config)
  const wpushRecipients = listEnabledWpushRecipients(config)
  const title = String(input.title || '订单系统通知').trim() || '订单系统通知'
  const body = String(input.body || '').trim()
  const category = String(input.category || 'system').trim() || 'system'

  if (config.enabled === false) {
    return {
      enabled: false,
      channel: 'internal',
      successCount: 0,
      failedCount: 0,
      skippedCount: barkRecipients.length + wpushRecipients.length,
      results: [] as NotificationResult[],
    }
  }

  const results = [
    ...(await Promise.all(
      barkRecipients.map(async (recipient: JsonObject) => {
        try {
          const result = await sendBarkNotification({
            recipient,
            title,
            body,
            group: `订单系统/${category}`,
            ...(bark.serverUrl !== undefined ? { serverUrl: bark.serverUrl } : {}),
            ...(input.url !== undefined ? { url: input.url } : {}),
          })
          return mapNotificationResult(
            'bark',
            recipient,
            recipient.deviceKey,
            true,
            '',
            result.status,
            result.response,
          )
        } catch (error) {
          logWarn('[notification/bark]', 'Bark 内部通知发送失败', {
            recipientId: recipient.id,
            recipientName: recipient.name,
            error,
          })
          return mapNotificationResult(
            'bark',
            recipient,
            recipient.deviceKey,
            false,
            error instanceof Error ? error.message : 'Bark 内部通知发送失败',
            isPlainObject(error) ? Number(error.statusCode || 0) || 0 : 0,
            isPlainObject(error) ? error.context || null : null,
          )
        }
      }),
    )),
    ...(await Promise.all(
      wpushRecipients.map(async (recipient: JsonObject) => {
        try {
          const result = await sendWpushNotification({
            recipient,
            title,
            body,
          })
          return mapNotificationResult(
            'wpush',
            recipient,
            recipient.apiKey,
            true,
            '',
            result.status,
            result.response,
          )
        } catch (error) {
          logWarn('[notification/wpush]', 'WPush 内部通知发送失败', {
            recipientId: recipient.id,
            recipientName: recipient.name,
            error,
          })
          return mapNotificationResult(
            'wpush',
            recipient,
            recipient.apiKey,
            false,
            error instanceof Error ? error.message : 'WPush 内部通知发送失败',
            isPlainObject(error) ? Number(error.statusCode || 0) || 0 : 0,
            isPlainObject(error) ? error.context || null : null,
          )
        }
      }),
    )),
  ]

  return {
    enabled: true,
    channel: 'internal',
    successCount: results.filter((item) => item.ok).length,
    failedCount: results.filter((item) => !item.ok).length,
    skippedCount: 0,
    results,
  }
}

function mapNotificationResult(
  channel: string,
  recipient: JsonObject,
  recipientKey: unknown,
  ok: boolean,
  errorMessage: string,
  status: number,
  response: unknown,
) {
  return {
    channel,
    recipientId: String(recipient.id || '').trim(),
    recipientName: String(recipient.name || '').trim(),
    recipientKeyMasked: maskSecretKey(recipientKey),
    ok,
    status,
    errorMessage,
    response,
  }
}

function maskSecretKey(value: unknown) {
  const normalized = String(value || '').trim()
  if (!normalized) {
    return ''
  }

  if (normalized.length <= 10) {
    return `${normalized.slice(0, 2)}****${normalized.slice(-2)}`
  }

  return `${normalized.slice(0, 6)}****${normalized.slice(-6)}`
}

function isPlainObject(value: unknown): value is JsonObject {
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
}
