import { z } from 'zod';

// ── Platform Event Schemas ───────────────────────────────────
// Each event type has a Zod schema for payload validation.
// Handlers receive typed payloads matching these schemas.

export const PlatformEventSchemas = {
  // Auth events
  'user.created': z.object({
    userId: z.string(),
    email: z.string(),
    plan: z.string(),
    productId: z.string(),
  }),
  'user.deleted': z.object({
    userId: z.string(),
    email: z.string(),
    productId: z.string(),
  }),
  'user.email_verified': z.object({
    userId: z.string(),
    email: z.string(),
    productId: z.string(),
  }),
  'user.password_reset': z.object({
    userId: z.string(),
    email: z.string(),
    resetToken: z.string(),
    displayName: z.string().optional(),
    productId: z.string(),
  }),
  'user.email_verification_requested': z.object({
    userId: z.string(),
    email: z.string(),
    verificationToken: z.string(),
    displayName: z.string().optional(),
    productId: z.string(),
  }),

  // SmartAuth events
  'auth.account_locked': z.object({
    userId: z.string(),
    email: z.string(),
    productId: z.string(),
    lockedUntil: z.string(),
    failedAttempts: z.number(),
  }),
  'auth.oauth_linked': z.object({
    userId: z.string(),
    provider: z.string(),
    providerEmail: z.string(),
    productId: z.string(),
  }),
  'auth.oauth_unlinked': z.object({
    userId: z.string(),
    provider: z.string(),
    productId: z.string(),
  }),
  'auth.membership_provisioned': z.object({
    userId: z.string(),
    productId: z.string(),
    plan: z.string(),
    role: z.string(),
  }),
  'auth.account_merged': z.object({
    primaryUserId: z.string(),
    secondaryUserId: z.string(),
    productId: z.string(),
  }),
  'auth.magic_link_requested': z.object({
    userId: z.string(),
    email: z.string(),
    token: z.string(),
    productId: z.string(),
    expiresAt: z.string(),
  }),

  // Subscription events
  'subscription.created': z.object({
    subscriptionId: z.string(),
    userId: z.string(),
    plan: z.string(),
    status: z.string(),
    productId: z.string(),
  }),
  'subscription.changed': z.object({
    subscriptionId: z.string(),
    userId: z.string(),
    oldPlan: z.string(),
    newPlan: z.string(),
    productId: z.string(),
  }),
  'subscription.canceled': z.object({
    subscriptionId: z.string(),
    userId: z.string(),
    reason: z.string().optional(),
    productId: z.string(),
  }),
  'subscription.trial_expiring': z.object({
    subscriptionId: z.string(),
    userId: z.string(),
    expiresAt: z.string(),
    productId: z.string(),
  }),
  'subscription.trial_expired': z.object({
    subscriptionId: z.string(),
    userId: z.string(),
    productId: z.string(),
  }),

  // Payment events
  'payment.succeeded': z.object({
    invoiceId: z.string(),
    userId: z.string(),
    amount: z.number(),
    currency: z.string(),
    productId: z.string(),
  }),
  'payment.failed': z.object({
    invoiceId: z.string(),
    userId: z.string(),
    amount: z.number(),
    currency: z.string().default('usd'),
    retryCount: z.number(),
    productId: z.string(),
  }),

  // Growth events
  'invitation.redeemed': z.object({
    invitationId: z.string(),
    userId: z.string(),
    productId: z.string(),
  }),
  'referral.completed': z.object({
    referralId: z.string(),
    referrerId: z.string(),
    referredId: z.string(),
    productId: z.string(),
  }),
  'waitlist.joined': z.object({
    email: z.string(),
    position: z.number(),
    productId: z.string(),
  }),

  // Feature flags
  'flag.toggled': z.object({
    flagId: z.string(),
    enabled: z.boolean(),
    percentage: z.number().optional(),
    productId: z.string(),
    flagKey: z.string().optional(),
    actor: z.string().optional(),
  }),
  'flag.created': z.object({
    productId: z.string(),
    flagKey: z.string(),
    actor: z.string().optional(),
  }),
  'flag.updated': z.object({
    productId: z.string(),
    flagKey: z.string(),
    actor: z.string().optional(),
    changes: z.array(z.string()).optional(),
  }),
  'flag.deleted': z.object({
    productId: z.string(),
    flagKey: z.string(),
    actor: z.string().optional(),
  }),
  'flag.kill_switch': z.object({
    productId: z.string(),
    disabled: z.array(z.string()),
    actor: z.string().optional(),
  }),

  // License events
  'license.activated': z.object({
    licenseId: z.string(),
    userId: z.string(),
    deviceId: z.string().optional(),
    productId: z.string(),
  }),
  'license.expired': z.object({
    licenseId: z.string(),
    userId: z.string(),
    productId: z.string(),
  }),

  // Job events
  'job.completed': z.object({
    jobName: z.string(),
    runId: z.string(),
    durationMs: z.number(),
    productId: z.string(),
  }),
  'job.failed': z.object({
    jobName: z.string(),
    runId: z.string(),
    error: z.string(),
    productId: z.string(),
  }),

  // Diagnostics events
  'diagnostics.session.created': z.object({
    sessionId: z.string(),
    productId: z.string(),
    targetUserId: z.string().optional(),
    targetAnonymousId: z.string().optional(),
    targetDeviceId: z.string().optional(),
    createdBy: z.string(),
  }),
  'diagnostics.session.started': z.object({
    sessionId: z.string(),
    productId: z.string(),
    startedAt: z.string(),
  }),
  'diagnostics.session.updated': z.object({
    sessionId: z.string(),
    productId: z.string(),
    changes: z.record(z.unknown()),
    updatedBy: z.string(),
  }),
  'diagnostics.session.cancelled': z.object({
    sessionId: z.string(),
    productId: z.string(),
    reason: z.string().optional(),
    cancelledBy: z.string(),
  }),
  'diagnostics.session.completed': z.object({
    sessionId: z.string(),
    productId: z.string(),
    stats: z.object({
      logCount: z.number(),
      traceCount: z.number(),
      screenshotCount: z.number(),
    }),
    endedAt: z.string(),
  }),
  'diagnostics.session.expired': z.object({
    sessionId: z.string(),
    productId: z.string(),
    expiredAt: z.string(),
  }),
  'diagnostics.ingest.fatal': z.object({
    sessionId: z.string(),
    productId: z.string(),
    logEntry: z.record(z.unknown()).optional(),
    timestamp: z.string(),
  }),
  'diagnostics.screenshot.captured': z.object({
    sessionId: z.string(),
    productId: z.string(),
    screenshotId: z.string(),
    trigger: z.enum(['manual', 'error', 'interval', 'user_request']),
  }),

  // Delivery events
  'delivery.email.requested': z.object({
    userId: z.string(),
    productId: z.string(),
    templateId: z.string(),
    context: z.record(z.unknown()).optional(),
  }),

  // Notifications events
  'notifications.push.requested': z.object({
    userId: z.string(),
    productId: z.string(),
    title: z.string(),
    body: z.string(),
    data: z.record(z.unknown()).optional(),
  }),
  'notifications.inapp.create': z.object({
    userId: z.string(),
    productId: z.string(),
    title: z.string(),
    content: z.string(),
    priority: z.enum(['high', 'normal', 'low']).optional(),
  }),

  // Integration events
  'integrations.slack.notify': z.object({
    channel: z.string(),
    message: z.record(z.unknown()),
  }),

  // Predictive analytics events
  'predictive.campaign.triggered': z.object({
    campaignId: z.string(),
    userId: z.string(),
    productId: z.string(),
    riskSegment: z.string(),
    channels: z.array(z.string()),
  }),
} as const;

// ── Derived Types ────────────────────────────────────────────

export type PlatformEventName = keyof typeof PlatformEventSchemas;

export type PlatformEventPayload<T extends PlatformEventName> = z.infer<
  (typeof PlatformEventSchemas)[T]
>;

export interface PlatformEvent<T extends PlatformEventName = PlatformEventName> {
  id: string;
  type: T;
  payload: PlatformEventPayload<T>;
  timestamp: string;
  source?: string;
}

export type EventHandler<T extends PlatformEventName = PlatformEventName> = (
  event: PlatformEvent<T>
) => void | Promise<void>;

export interface EventSubscription {
  id: string;
  eventType: PlatformEventName;
  unsubscribe: () => void;
}
