/* eslint-disable no-redeclare */
/**
 * Broadcast types — targeted messaging with segmentation
 * @module broadcasts/types
 */

import { z } from 'zod';

// =============================================================================
// Enums & Constants
// =============================================================================

export const BroadcastStatus = {
  DRAFT: 'draft',
  SCHEDULED: 'scheduled',
  SENDING: 'sending',
  SENT: 'sent',
  PAUSED: 'paused',
} as const;

export type BroadcastStatus = (typeof BroadcastStatus)[keyof typeof BroadcastStatus];

export const BroadcastChannel = {
  PUSH: 'push',
  IN_APP: 'in_app',
  EMAIL: 'email',
} as const;

export type BroadcastChannel = (typeof BroadcastChannel)[keyof typeof BroadcastChannel];

export const BroadcastVariant = {
  CONTROL: 'control',
  TREATMENT: 'treatment',
} as const;

export type BroadcastVariant = (typeof BroadcastVariant)[keyof typeof BroadcastVariant];

export const UserSegment = {
  FREE: 'free',
  PRO: 'pro',
  ENTERPRISE: 'enterprise',
  CHURNED: 'churned',
  ACTIVE: 'active',
} as const;

export type UserSegment = (typeof UserSegment)[keyof typeof UserSegment];

export const Platform = {
  IOS: 'ios',
  ANDROID: 'android',
  WEB: 'web',
  MACOS: 'macos',
  WINDOWS: 'windows',
} as const;

export type Platform = (typeof Platform)[keyof typeof Platform];

// =============================================================================
// Core Interfaces (Stored in Cosmos)
// =============================================================================

export interface Broadcast {
  id: string;
  productId: string;
  title: string;
  body: string;
  bodyMarkdown?: string;
  ctaText?: string;
  ctaUrl?: string;
  imageUrl?: string;

  // Rich Media (multiple images/videos supported)
  media?: BroadcastMedia[];

  // Targeting
  target: BroadcastTarget;

  // Channels
  channels: BroadcastChannel[];

  // Scheduling
  status: BroadcastStatus;
  scheduledAt?: string;
  sentAt?: string;

  // A/B Testing
  variant?: BroadcastVariant;
  experimentId?: string;
  parentBroadcastId?: string; // For cloned A/B variants

  // Metrics
  metrics: BroadcastMetrics;

  createdAt: string;
  updatedAt: string;
  createdBy: string;
}

export interface BroadcastTarget {
  // User segments (OR logic within array, AND with other criteria)
  userSegments?: UserSegment[];

  // Platform targeting
  platforms?: Platform[];

  // App version range (semver)
  appVersionMin?: string;
  appVersionMax?: string;

  // Geo targeting
  countryCodes?: string[]; // ISO 3166-1 alpha-2
  regionCodes?: string[]; // e.g., 'US-CA', 'EU-DE'

  // OS version
  osVersionMin?: string;
  osVersionMax?: string;

  // Percentage rollout (0-100, uses FNV-1a hash like feature flags)
  percentageRollout?: number;

  // Explicit user IDs (for testing)
  specificUserIds?: string[];
}

// Rich Media Content
export interface BroadcastMedia {
  type: 'image' | 'video' | 'gif' | 'audio';
  url: string;
  thumbnailUrl?: string;
  width?: number;
  height?: number;
  duration?: number; // For video/audio in seconds
  size?: number; // File size in bytes
  mimeType?: string;
}

// Engagement Metrics with rich media tracking
export interface BroadcastMetrics {
  targetedCount: number;
  sentCount: number;
  deliveredCount: number;
  openedCount: number;
  clickedCount: number;
  dismissedCount: number;
  convertedCount: number;
  // Rich media engagement
  mediaViewedCount?: number;
  mediaCompletedCount?: number;
  mediaClickedCount?: number;
}

// =============================================================================
// Delivery Tracking (per-user)
// =============================================================================

export interface BroadcastDelivery {
  id: string; // composite: `${broadcastId}:${userId}`
  broadcastId: string;
  userId: string;
  productId: string;

  // Delivery status per channel
  pushStatus: 'pending' | 'sent' | 'delivered' | 'failed' | 'bounced';
  inAppStatus: 'pending' | 'sent' | 'delivered' | 'dismissed' | 'read';
  emailStatus: 'pending' | 'sent' | 'delivered' | 'failed' | 'bounced';

  // Timestamps
  pushSentAt?: string;
  pushDeliveredAt?: string;
  inAppDeliveredAt?: string;
  emailSentAt?: string;

  // Engagement
  openedAt?: string;
  clickedAt?: string;
  dismissedAt?: string;
  convertedAt?: string;

  createdAt: string;
  updatedAt: string;
}

// In-app message queue (per-user)
export interface InAppMessage {
  id: string;
  userId: string;
  productId: string;
  broadcastId: string;

  // Content
  title: string;
  body: string;
  bodyMarkdown?: string;
  ctaText?: string;
  ctaUrl?: string;

  // Rich Media
  media?: BroadcastMedia[];
  imageUrl?: string; // Legacy support

  priority: 'low' | 'normal' | 'high' | 'urgent';
  style: 'banner' | 'modal' | 'toast' | 'fullscreen';
  dismissible: boolean;
  expiresAt?: string;

  // Status
  status: 'unread' | 'read' | 'dismissed';

  createdAt: string;
  updatedAt: string;
}

// Read receipts (simpler than full delivery tracking)
export interface BroadcastRead {
  id: string; // composite: `${broadcastId}:${userId}`
  broadcastId: string;
  userId: string;
  productId: string;
  readAt?: string;
  clickedAt?: string;
  dismissedAt?: string;
  createdAt: string;
  updatedAt?: string;
}

// =============================================================================
// Zod Schemas (for input validation)
// =============================================================================

export const BroadcastTargetSchema = z.object({
  userSegments: z.array(z.nativeEnum(UserSegment)).optional(),
  platforms: z.array(z.nativeEnum(Platform)).optional(),
  appVersionMin: z.string().optional(),
  appVersionMax: z.string().optional(),
  countryCodes: z.array(z.string().length(2)).optional(),
  regionCodes: z.array(z.string()).optional(),
  osVersionMin: z.string().optional(),
  osVersionMax: z.string().optional(),
  percentageRollout: z.number().min(0).max(100).optional(),
  specificUserIds: z.array(z.string()).optional(),
});

export const CreateBroadcastSchema = z.object({
  title: z.string().min(1).max(200),
  body: z.string().min(1).max(2000),
  bodyMarkdown: z.string().max(5000).optional(),
  ctaText: z.string().max(50).optional(),
  ctaUrl: z.string().url().max(500).optional(),
  imageUrl: z.string().url().optional(),
  media: z
    .array(
      z.object({
        type: z.enum(['image', 'video', 'gif', 'audio']),
        url: z.string().url(),
        thumbnailUrl: z.string().url().optional(),
        width: z.number().optional(),
        height: z.number().optional(),
        duration: z.number().optional(),
        size: z.number().optional(),
        mimeType: z.string().optional(),
      })
    )
    .optional(),
  target: BroadcastTargetSchema,
  channels: z.array(z.nativeEnum(BroadcastChannel)).min(1),
  scheduledAt: z.string().datetime().optional(),
  variant: z.nativeEnum(BroadcastVariant).optional(),
  experimentId: z.string().optional(),
  parentBroadcastId: z.string().optional(),
});

export const UpdateBroadcastSchema = z.object({
  title: z.string().min(1).max(200).optional(),
  body: z.string().min(1).max(2000).optional(),
  bodyMarkdown: z.string().max(5000).optional(),
  ctaText: z.string().max(50).optional(),
  ctaUrl: z.string().url().max(500).optional(),
  imageUrl: z.string().url().optional(),
  target: BroadcastTargetSchema.optional(),
  channels: z.array(z.nativeEnum(BroadcastChannel)).min(1).optional(),
  scheduledAt: z.string().datetime().optional(),
  status: z.nativeEnum(BroadcastStatus).optional(),
});

export const InAppMessageActionSchema = z.object({
  action: z.enum(['read', 'dismiss', 'click']),
});

// =============================================================================
// Targeting Context (runtime, not stored)
// =============================================================================

export interface TargetingContext {
  userId: string;
  productId: string;
  platform: Platform;
  appVersion: string;
  osVersion: string;
  countryCode?: string;
  regionCode?: string;
  userSegments: UserSegment[];
}

// =============================================================================
// Response Types
// =============================================================================

export interface EstimateReachResult {
  estimatedCount: number;
  targetBreakdown: {
    userSegments: Record<string, number>;
    platforms: Record<string, number>;
    countries: Record<string, number>;
  };
  sampleUserIds: string[]; // First 5 matched users
}
