import type { Message, MessageBatch } from '@cloudflare/workers-types'
import { buildMailMessage } from '@zync/notifications'
import type { Env } from '@zync/types'
import { sendMail } from '../integrations/platform/mail'
import type { AuthEmailMessage } from '../adapters/email'

type AuthEmailJob = { type: 'auth.email' } & AuthEmailMessage

function isAuthEmailJob(value: unknown): value is AuthEmailJob {
  if (!value || typeof value !== 'object') return false
  const job = value as Partial<AuthEmailJob>
  if (job.type !== 'auth.email' || typeof job.kind !== 'string' || typeof job.to !== 'string') return false
  if (job.kind === 'verify_email' || job.kind === 'password_reset') {
    return typeof job.token === 'string' && typeof job.userId === 'string'
  }
  if (job.kind === 'invitation') {
    return typeof job.token === 'string' && typeof job.tenantId === 'string' && typeof job.invitedBy === 'string'
  }
  if (job.kind === 'email_change_verify') {
    return typeof job.verifyUrl === 'string' && typeof job.userId === 'string'
  }
  return job.kind === 'email_change_requested' && typeof job.newEmail === 'string' && typeof job.userId === 'string'
}

function appOrigin(job: AuthEmailJob, env: Pick<Env, 'APP_BASE_URL'>): string {
  const configured = (job.appOrigin ?? env.APP_BASE_URL)?.trim()
  if (!configured) throw new Error('APP_BASE_URL is required for auth email delivery')
  const url = new URL(configured)
  if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) {
    throw new Error('APP_BASE_URL must be an absolute HTTP(S) origin')
  }
  return url.origin
}

function link(origin: string, pathname: string, token: string): string {
  return `${origin}${pathname}?token=${encodeURIComponent(token)}`
}

function buildAuthMail(job: AuthEmailJob, origin: string) {
  switch (job.kind) {
    case 'verify_email':
      return buildMailMessage({
        to: job.to,
        templateKey: 'verification',
        locale: 'he-IL',
        vars: {
          subject: 'אימות כתובת הדוא״ל שלך ב-Zync',
          title: 'אימות כתובת הדוא״ל',
          body: 'לחצו על הקישור כדי לאמת את כתובת הדוא״ל ולהפעיל את סביבת העבודה שלכם.',
          verificationUrl: link(origin, '/api/auth/verify-email', job.token),
          ctaLabel: 'אימות כתובת הדוא״ל',
        },
      })
    case 'password_reset':
      return buildMailMessage({
        to: job.to,
        templateKey: 'password-reset',
        locale: 'he-IL',
        vars: {
          subject: 'איפוס הסיסמה שלך ב-Zync',
          title: 'איפוס סיסמה',
          body: 'קיבלתם את ההודעה הזו כי התבקש איפוס סיסמה לחשבון שלכם.',
          resetUrl: link(origin, '/reset-password/confirm', job.token),
          ctaLabel: 'איפוס סיסמה',
          expiryNote: 'הקישור תקף לשעה אחת.',
        },
      })
    case 'invitation':
      return buildMailMessage({
        to: job.to,
        templateKey: 'invitation',
        locale: 'he-IL',
        vars: {
          subject: 'הוזמנתם להצטרף ל-Zync',
          title: 'הזמנה להצטרף לסביבת עבודה',
          body: 'קיבלתם הזמנה להצטרף לסביבת עבודה ב-Zync.',
          inviteUrl: link(origin, '/invite/accept', job.token),
          ctaLabel: 'קבלת ההזמנה',
        },
      })
    case 'email_change_verify':
      return buildMailMessage({
        to: job.to,
        templateKey: 'verification',
        locale: 'he-IL',
        vars: {
          subject: 'אימות כתובת דוא״ל חדשה ב-Zync',
          title: 'אימות כתובת דוא״ל חדשה',
          body: 'לחצו על הקישור כדי לאמת את כתובת הדוא״ל החדשה.',
          verificationUrl: job.verifyUrl,
          ctaLabel: 'אימות כתובת הדוא״ל',
        },
      })
    case 'email_change_requested':
      return buildMailMessage({
        to: job.to,
        templateKey: 'verification',
        locale: 'he-IL',
        vars: {
          subject: 'התבקשה החלפת כתובת דוא״ל ב-Zync',
          title: 'התבקשה החלפת כתובת דוא״ל',
          body: `התבקשה החלפת כתובת הדוא״ל ל-${job.newEmail}. אם לא ביקשתם זאת, אבטחו את החשבון שלכם.`,
          verificationUrl: origin,
          ctaLabel: 'כניסה ל-Zync',
        },
      })
  }
}

async function handleMessage(message: Message<unknown>, env: Env): Promise<void> {
  if (!isAuthEmailJob(message.body)) {
    message.ack()
    return
  }

  try {
    const mail = buildAuthMail(message.body, appOrigin(message.body, env))
    await sendMail(env, {
      ...mail,
      idempotencyKey: `auth-email:${message.id}`,
    })
    message.ack()
  } catch (error) {
    console.error('[auth-email] delivery failed', { messageId: message.id, attempts: message.attempts, error })
    message.retry({ delaySeconds: Math.min(300, 30 * 2 ** Math.max(0, message.attempts - 1)) })
  }
}

export async function handleAuthEmailMessages(batch: MessageBatch<unknown>, env: Env): Promise<void> {
  for (const message of batch.messages) await handleMessage(message, env)
}
