import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
import { HydratedDocument, Types } from 'mongoose'
import type { WebhookEvent } from './webhook-subscription.schema.js'

export type WebhookDeliveryDocument = HydratedDocument<WebhookDelivery>

// 'pending'   — queued, waiting for the delivery worker (nextAttemptAt due).
// 'delivered' — receiver returned 2xx.
// 'failed'    — exhausted maxAttempts; terminal.
export type WebhookDeliveryStatus = 'pending' | 'delivered' | 'failed'

// One outbound delivery attempt-set for a single (subscription, event) pair. The
// payload + signature are captured at enqueue time so retries replay the exact
// same signed body. The @nestjs/schedule worker claims due 'pending' rows,
// POSTs them, and on non-2xx schedules an exponential backoff retry until
// maxAttempts is reached.
@Schema({ collection: 'scheduling_webhook_deliveries', timestamps: true })
export class WebhookDelivery {
  @Prop({ type: Types.ObjectId, ref: 'Tenant', required: true, index: true })
  tenantId!: Types.ObjectId

  @Prop({ type: Types.ObjectId, ref: 'WebhookSubscription', required: true, index: true })
  subscriptionId!: Types.ObjectId

  @Prop({ required: true })
  event!: WebhookEvent

  @Prop({ required: true })
  url!: string

  // The exact JSON body string that was signed (so retries are byte-identical).
  @Prop({ required: true })
  payload!: string

  // Hex HMAC-SHA256 of `payload` under the subscription secret. Sent as the
  // X-Dezky-Signature header.
  @Prop({ required: true })
  signature!: string

  @Prop({ enum: ['pending', 'delivered', 'failed'], default: 'pending', index: true })
  status!: WebhookDeliveryStatus

  @Prop({ default: 0 })
  attempts!: number

  @Prop({ required: true, default: 8 })
  maxAttempts!: number

  // When the next attempt is due. The worker polls for due 'pending' rows.
  @Prop({ required: true, index: true })
  nextAttemptAt!: Date

  @Prop()
  lastError?: string

  @Prop()
  lastStatusCode?: number

  @Prop()
  deliveredAt?: Date
}

export const WebhookDeliverySchema = SchemaFactory.createForClass(WebhookDelivery)
