import type { JsonObject } from '../../types/json.js'
import { logWarn } from '../../utils/logger.js'
import { sendInternalNotification } from './notification-service.js'

const DEFAULT_COOLDOWN_MS = 10 * 60 * 1000
const notificationCooldownMap = new Map<string, number>()

type InternalNotificationPayload = {
  title: string
  body?: string
  category?: string
  url?: string
  cooldownKey?: string
  cooldownMs?: number
}
type KuaishouCloudAssetNotEnoughPayload = {
  task?: unknown
  flow?: unknown
  assetBefore?: unknown
  requiredAsset?: unknown
  skuName?: unknown
}
type CloudtentaclesAuthExpiredPayload = {
  pathname?: unknown
  errorCode?: unknown
  message?: unknown
  cooldownSeconds?: unknown
  sourceKey?: unknown
  accountLabel?: unknown
}
type CloudtentaclesAssetLowPayload = {
  asset?: unknown
  threshold?: unknown
  cooldownSeconds?: unknown
  sourceKey?: unknown
  accountLabel?: unknown
}
type Open91PendingConfigPayload = {
  order?: unknown
  orderNo?: unknown
  productNo?: unknown
  buyNum?: unknown
  reason?: unknown
}
type TaskNotificationPayload = {
  task?: unknown
  reason?: unknown
  source?: unknown
  errorMessage?: unknown
}
type ClaimRedeemNeedsAttentionPayload = {
  task?: unknown
  order?: unknown
  status?: unknown
  errorMessage?: unknown
}

export async function notifyInternalSafely(payload: InternalNotificationPayload) {
  const cooldownKey = String(payload.cooldownKey || '').trim()
  if (cooldownKey && isNotificationCoolingDown(cooldownKey, payload.cooldownMs)) {
    return {
      skipped: true,
      reason: 'cooldown',
    }
  }

  try {
    const result = await sendInternalNotification({
      title: payload.title,
      ...(payload.body !== undefined ? { body: payload.body } : {}),
      ...(payload.category !== undefined ? { category: payload.category } : {}),
      ...(payload.url !== undefined ? { url: payload.url } : {}),
    })
    markNotificationCooldown(cooldownKey)
    return result
  } catch (error) {
    logWarn('[notification/internal]', '内部通知发送失败，已跳过', {
      title: payload.title,
      category: payload.category,
      error,
    })
    markNotificationCooldown(cooldownKey)
    return {
      skipped: true,
      reason: 'send_failed',
    }
  }
}

export function notifyKuaishouCloudAssetNotEnough({
  task = {},
  flow = {},
  assetBefore = 0,
  requiredAsset = 0,
  skuName = '',
}: KuaishouCloudAssetNotEnoughPayload = {}) {
  const taskRecord = toRecord(task)
  const flowRecord = toRecord(flow)
  const binding = toRecord(flowRecord.binding)

  return notifyInternalSafely({
    title: 'kuaishou-lewan 余额不足',
    body: [
      formatTaskLine(taskRecord),
      `当前余额：${Number(assetBefore || 0)}`,
      `最低需要：${Number(requiredAsset || 0)}`,
      `商品：${String(skuName || binding.skuName || flowRecord.internalSkuName || '').trim() || '-'}`,
    ].join('\n'),
    category: 'kuaishou_cloud_asset_not_enough',
    cooldownKey: ['kuaishou_cloud_asset_not_enough', taskRecord.id || '', binding.skuId || ''].join(
      ':',
    ),
  })
}

export function notifyCloudtentaclesAuthExpired({
  pathname = '',
  errorCode = '',
  message = '',
  cooldownSeconds = 600,
  sourceKey = '',
  accountLabel = '',
}: CloudtentaclesAuthExpiredPayload = {}) {
  const normalizedSourceKey = String(sourceKey || '').trim()
  const normalizedAccountLabel = String(accountLabel || '').trim()

  return notifyInternalSafely({
    title: normalizedAccountLabel
      ? `cloudtentacles 登录已过期：${normalizedAccountLabel}`
      : 'cloudtentacles 登录已过期',
    body: [
      normalizedSourceKey ? `账号：${normalizedAccountLabel || normalizedSourceKey}` : '',
      `接口：${String(pathname || '').trim() || '-'}`,
      `错误码：${String(errorCode || '').trim() || '-'}`,
      `原因：${String(message || '').trim() || '登录态已失效，请到后台重新登录'}`,
    ]
      .filter(Boolean)
      .join('\n'),
    category: 'cloudtentacles_auth_expired',
    cooldownKey: [
      'cloudtentacles_auth_expired',
      normalizedSourceKey || 'default',
      pathname,
      errorCode,
    ].join(':'),
    cooldownMs: Number(cooldownSeconds || 600) * 1000,
  })
}

export function notifyCloudtentaclesAssetLow({
  asset = 0,
  threshold = 500,
  cooldownSeconds = 1800,
  sourceKey = '',
  accountLabel = '',
}: CloudtentaclesAssetLowPayload = {}) {
  const normalizedSourceKey = String(sourceKey || '').trim()
  const normalizedAccountLabel = String(accountLabel || '').trim()

  return notifyInternalSafely({
    title: normalizedAccountLabel
      ? `kuaishou-lewan 余额低于阈值：${normalizedAccountLabel}`
      : 'kuaishou-lewan 余额低于阈值',
    body: [
      normalizedSourceKey ? `账号：${normalizedAccountLabel || normalizedSourceKey}` : '',
      `当前余额：${Number(asset || 0)}`,
      `提醒阈值：${Number(threshold || 0)}`,
      '请及时补充 cloudtentacles 余额，避免自动履约失败。',
    ]
      .filter(Boolean)
      .join('\n'),
    category: 'cloudtentacles_asset_low',
    cooldownKey: ['cloudtentacles_asset_low', normalizedSourceKey || 'default', threshold].join(
      ':',
    ),
    cooldownMs: Number(cooldownSeconds || 1800) * 1000,
  })
}

export function notifyOpen91PendingConfig({
  order = {},
  orderNo = '',
  productNo = '',
  buyNum = 0,
  reason = '未命中履约配置',
}: Open91PendingConfigPayload = {}) {
  const orderRecord = toRecord(order)

  return notifyInternalSafely({
    title: '91卡券订单待补配置',
    body: [
      `订单：${String(orderNo || orderRecord.platform_order_id || '').trim() || '-'}`,
      `商品：${String(productNo || '').trim() || '-'}`,
      `数量：${Number(buyNum || 0) || 0}`,
      `原因：${String(reason || '').trim() || '未命中履约配置'}`,
    ].join('\n'),
    category: 'open91_pending_config',
    cooldownKey: [
      'open91_pending_config',
      orderNo || orderRecord.platform_order_id || '',
      productNo,
    ].join(':'),
  })
}

export function notifyKuaishouCloudBindUrlRefreshFailed({
  task = {},
  errorMessage = '',
}: TaskNotificationPayload = {}) {
  const taskRecord = toRecord(task)

  return notifyInternalSafely({
    title: 'kuaishou-lewan 链接刷新失败',
    body: [
      formatTaskLine(taskRecord),
      `原因：${String(errorMessage || taskRecord.last_error || '').trim() || '-'}`,
      '旧虚拟号已退还，新绑定链接未准备成功。',
    ].join('\n'),
    category: 'kuaishou_cloud_bind_url_refresh_failed',
    cooldownKey: ['kuaishou_cloud_bind_url_refresh_failed', taskRecord.id || ''].join(':'),
  })
}

export function notifyTaskAutoManualReview({
  task = {},
  reason = '',
  source = '',
}: TaskNotificationPayload = {}) {
  const taskRecord = toRecord(task)

  return notifyInternalSafely({
    title: '任务已自动转人工处理',
    body: [
      formatTaskLine(taskRecord),
      `来源：${String(source || '').trim() || '-'}`,
      `原因：${String(reason || taskRecord.last_error || '').trim() || '-'}`,
    ].join('\n'),
    category: 'task_auto_manual_review',
    cooldownKey: ['task_auto_manual_review', taskRecord.id || '', source].join(':'),
  })
}

export function notifyClaimRedeemNeedsAttention({
  task = {},
  order = {},
  status = '',
  errorMessage = '',
}: ClaimRedeemNeedsAttentionPayload = {}) {
  const taskRecord = toRecord(task)
  const orderRecord = toRecord(order)

  return notifyInternalSafely({
    title: '兑换失败，任务需关注',
    body: [
      formatTaskLine(taskRecord),
      `订单：${String(orderRecord.platform_order_id || taskRecord.platform_order_id || '').trim() || '-'}`,
      `状态：${String(status || taskRecord.task_status || '').trim() || '-'}`,
      `原因：${String(errorMessage || taskRecord.last_error || '').trim() || '-'}`,
    ].join('\n'),
    category: 'claim_redeem_failed',
    cooldownKey: ['claim_redeem_needs_attention', taskRecord.id || '', status].join(':'),
  })
}

function formatTaskLine(task: unknown) {
  const taskRecord = toRecord(task)
  return [
    `任务：${String(taskRecord.task_no || taskRecord.id || '').trim() || '-'}`,
    `平台订单：${String(taskRecord.platform_order_id || '').trim() || '-'}`,
  ].join(' / ')
}

function toRecord(value: unknown): JsonObject {
  return value && typeof value === 'object' && !Array.isArray(value) ? (value as JsonObject) : {}
}

function isNotificationCoolingDown(cooldownKey: unknown, cooldownMs = DEFAULT_COOLDOWN_MS) {
  const key = String(cooldownKey || '').trim()
  if (!key) {
    return false
  }

  const lastSentAt = Number(notificationCooldownMap.get(key) || 0)
  return Date.now() - lastSentAt < Number(cooldownMs || DEFAULT_COOLDOWN_MS)
}

function markNotificationCooldown(cooldownKey: unknown) {
  const key = String(cooldownKey || '').trim()
  if (!key) {
    return
  }

  notificationCooldownMap.set(key, Date.now())
}
