/**
 * Subscriber email notifications for system incidents — system-status-page.
 *
 * Sends email to all status_subscribers when an incident is created, updated,
 * or resolved. Each email includes an unsubscribe link with the recipient's
 * token.
 *
 * Failures per-recipient are logged but do not abort the rest of the batch.
 * Subscribers are processed in chunks of 50 to avoid one enormous fan-out.
 */
import { createDb } from '@zync/db/queries'
import { listSubscribers } from '@zync/db/queries'
import { sendEmail } from '@zync/notifications'
import type { Env } from '@zync/types'
import type { IncidentObject } from '@zync/types'

const BATCH_SIZE = 50
// Unsubscribe / status page are served from api.zync.is (/status/* routes)
const BASE_URL = 'https://api.zync.is'
const STATUS_PAGE_URL = 'https://zync.is/status'

function buildSubject(
  kind: 'created' | 'updated' | 'resolved',
  incident: IncidentObject,
): string {
  switch (kind) {
    case 'created':
      return `[Zync Status] Incident: ${incident.title}`
    case 'updated':
      return `[Zync Status] Update: ${incident.title}`
    case 'resolved':
      return `[Zync Status] Resolved: ${incident.title}`
  }
}

function buildBody(
  kind: 'created' | 'updated' | 'resolved',
  incident: IncidentObject,
  unsubscribeToken: string,
): string {
  const latestUpdate = incident.updates[0]
  const updateText = latestUpdate ? latestUpdate.body : ''
  const unsubscribeUrl = `${BASE_URL}/status/unsubscribe?token=${unsubscribeToken}`

  const lines: string[] = [
    `${incident.title}`,
    `Status: ${incident.status} | Impact: ${incident.impact}`,
    `Services affected: ${incident.affectedServices.join(', ') || 'none'}`,
    '',
  ]

  if (updateText) {
    lines.push(`Latest update: ${updateText}`, '')
  }

  if (kind === 'resolved') {
    lines.push('This incident has been resolved.', '')
  }

  lines.push(`View full status: ${STATUS_PAGE_URL}`)
  lines.push(`Unsubscribe: ${unsubscribeUrl}`)

  return lines.join('\n')
}

/**
 * Notify all current subscribers about an incident lifecycle event.
 */
export async function notifySubscribers(
  env: Env,
  kind: 'created' | 'updated' | 'resolved',
  incident: IncidentObject,
): Promise<void> {
  const db = createDb(env)
  const subscribers = await listSubscribers(db)

  if (subscribers.length === 0) return

  // Process in batches of BATCH_SIZE
  for (let i = 0; i < subscribers.length; i += BATCH_SIZE) {
    const batch = subscribers.slice(i, i + BATCH_SIZE)

    await Promise.allSettled(
      batch.map(async (sub) => {
        const subject = buildSubject(kind, incident)
        const body = buildBody(kind, incident, sub.unsubscribeToken)

        try {
          await sendEmail(
            {
              to: sub.email,
              templateKey: 'status_incident_notification',
              vars: {
                subject,
                incidentTitle: incident.title,
                incidentStatus: incident.status,
                incidentImpact: incident.impact,
                affectedServices: incident.affectedServices.join(', '),
                updateBody: body,
                unsubscribeUrl: `${BASE_URL}/status/unsubscribe?token=${sub.unsubscribeToken}`,
                statusPageUrl: STATUS_PAGE_URL,
              },
              // status notifications are infrastructure; fall back to he-IL (IL-first)
              locale: 'he-IL',
            },
            env,
          )
        } catch (err) {
          // Log but do not re-throw — one failed recipient must not abort others
          console.error(
            `[status-notify] Failed to send to ${sub.email}:`,
            err instanceof Error ? err.message : String(err),
          )
        }
      }),
    )
  }
}
