import path from 'node:path'
import type { JsonObject } from '../../types/json.js'

import { APP_CONFIG_KEYS } from '../../config/app-config-keys.js'
import { PROJECT_ROOT } from '../../config/runtime.js'
import { readAppConfigEntry, saveAppConfigEntry } from '../config/app-config-store.js'

const NOTIFICATION_CONFIG_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'notification-config.json')
const DEFAULT_BARK_SERVER_URL = 'https://api.day.app'

type NotificationRecipient = {
  id: string
  name: string
  deviceKey?: string
  apiKey?: string
  enabled: boolean
}

export function getNotificationConfigFilePath() {
  return NOTIFICATION_CONFIG_FILE_PATH
}

export function getNotificationConfig() {
  return readAppConfigEntry({
    configKey: APP_CONFIG_KEYS.notification,
    legacyFilePath: NOTIFICATION_CONFIG_FILE_PATH,
    fallback: createDefaultNotificationConfig,
    normalize: normalizeNotificationConfig,
  })
}

export function saveNotificationConfig(rawValue: unknown) {
  return saveAppConfigEntry({
    configKey: APP_CONFIG_KEYS.notification,
    legacyFilePath: NOTIFICATION_CONFIG_FILE_PATH,
    value: rawValue,
    normalize: normalizeNotificationConfig,
  })
}

export function listEnabledBarkRecipients(config: JsonObject = getNotificationConfig()) {
  if (config.enabled === false || config.channels?.bark?.enabled === false) {
    return []
  }

  return (
    Array.isArray(config.channels?.bark?.recipients) ? config.channels.bark.recipients : []
  ).filter((item: JsonObject) => item.enabled !== false && String(item.deviceKey || '').trim())
}

export function listEnabledWpushRecipients(config: JsonObject = getNotificationConfig()) {
  if (config.enabled === false || config.channels?.wpush?.enabled === false) {
    return []
  }

  return (
    Array.isArray(config.channels?.wpush?.recipients) ? config.channels.wpush.recipients : []
  ).filter(
    (item: JsonObject) => item.enabled !== false && String(item.apiKey || item.apikey || '').trim(),
  )
}

export function normalizeNotificationConfig(rawValue: unknown) {
  const source = isPlainObject(rawValue) ? rawValue : {}
  const bark = isPlainObject(source.channels?.bark) ? source.channels.bark : {}
  const wpush = isPlainObject(source.channels?.wpush) ? source.channels.wpush : {}

  return {
    enabled: typeof source.enabled === 'boolean' ? source.enabled : true,
    channels: {
      bark: {
        enabled: typeof bark.enabled === 'boolean' ? bark.enabled : true,
        serverUrl: normalizeBarkServerUrl(bark.serverUrl),
        recipients: (Array.isArray(bark.recipients) ? bark.recipients : [])
          .map((item: unknown) => normalizeBarkRecipient(item))
          .filter(Boolean),
      },
      wpush: {
        enabled: typeof wpush.enabled === 'boolean' ? wpush.enabled : true,
        recipients: (Array.isArray(wpush.recipients) ? wpush.recipients : [])
          .map((item: unknown) => normalizeWpushRecipient(item))
          .filter(Boolean),
      },
    },
  }
}

function normalizeBarkRecipient(rawValue: unknown): NotificationRecipient | null {
  if (!isPlainObject(rawValue)) {
    return null
  }

  const name = String(rawValue.name || '').trim()
  const deviceKey = String(rawValue.deviceKey || '').trim()
  const id = String(rawValue.id || deviceKey || name || '').trim()

  if (!name && !deviceKey) {
    return null
  }

  return {
    id,
    name,
    deviceKey,
    enabled: typeof rawValue.enabled === 'boolean' ? rawValue.enabled : true,
  }
}

function normalizeBarkServerUrl(value: unknown) {
  const normalized = String(value || DEFAULT_BARK_SERVER_URL).trim() || DEFAULT_BARK_SERVER_URL
  return normalized.replace(/\/+$/, '')
}

function normalizeWpushRecipient(rawValue: unknown): NotificationRecipient | null {
  if (!isPlainObject(rawValue)) {
    return null
  }

  const name = String(rawValue.name || '').trim()
  const apiKey = String(rawValue.apiKey || rawValue.apikey || '').trim()
  const id = String(rawValue.id || apiKey || name || '').trim()

  if (!name && !apiKey) {
    return null
  }

  return {
    id,
    name,
    apiKey,
    enabled: typeof rawValue.enabled === 'boolean' ? rawValue.enabled : true,
  }
}

export function createDefaultNotificationConfig() {
  return {
    enabled: true,
    channels: {
      bark: {
        enabled: true,
        serverUrl: DEFAULT_BARK_SERVER_URL,
        recipients: [] as NotificationRecipient[],
      },
      wpush: {
        enabled: true,
        recipients: [] as NotificationRecipient[],
      },
    },
  }
}

function isPlainObject(value: unknown): value is JsonObject {
  return Object.prototype.toString.call(value) === '[object Object]'
}
