/**
 * Session Replay Types — Remote Diagnostics Phase 4
 * DOM/View state capture for video-style replay.
 */

import { z } from 'zod';

// ─────────────────────────────────────────────────────────────────────────────
// Replay Event Types
// ─────────────────────────────────────────────────────────────────────────────

export const ReplayEventTypeEnum = z.enum([
  'initial_state',
  'dom_mutation',
  'view_change',
  'user_interaction',
  'network_request',
  'console_log',
  'error',
  'scroll',
  'resize',
]);

export type ReplayEventType = z.infer<typeof ReplayEventTypeEnum>;

// ─────────────────────────────────────────────────────────────────────────────
// Base Replay Event
// ─────────────────────────────────────────────────────────────────────────────

export interface ReplayEvent {
  id: string;
  sessionId: string;
  timestamp: number; // milliseconds since session start
  type: ReplayEventType;
  data: Record<string, unknown>;
}

// ─────────────────────────────────────────────────────────────────────────────
// Specific Event Types
// ─────────────────────────────────────────────────────────────────────────────

export interface InitialStateEvent extends ReplayEvent {
  type: 'initial_state';
  data: {
    url: string;
    viewport: { width: number; height: number };
    domSnapshot?: string; // Serialized DOM (privacy-sanitized)
    viewHierarchy?: string; // For native apps (iOS/Android)
    styles?: Record<string, string>; // CSS styles
  };
}

export interface DOMMutationEvent extends ReplayEvent {
  type: 'dom_mutation';
  data: {
    target: string; // CSS selector or element path
    mutationType: 'childList' | 'attributes' | 'characterData';
    addedNodes?: string[];
    removedNodes?: string[];
    attributeName?: string;
    attributeValue?: string;
    oldValue?: string;
  };
}

export interface ViewChangeEvent extends ReplayEvent {
  type: 'view_change';
  data: {
    viewName: string;
    viewId?: string;
    viewController?: string; // iOS: UIViewController, Android: Activity/Fragment
    params?: Record<string, unknown>;
  };
}

export interface UserInteractionEvent extends ReplayEvent {
  type: 'user_interaction';
  data: {
    interactionType: 'click' | 'tap' | 'input' | 'focus' | 'blur' | 'hover' | 'keypress';
    target: string; // CSS selector or element path
    x?: number; // Coordinates for click/tap
    y?: number;
    value?: string; // For input fields (sanitized - no passwords)
    key?: string; // For keypress events
  };
}

export interface ScrollEvent extends ReplayEvent {
  type: 'scroll';
  data: {
    target: string;
    scrollX: number;
    scrollY: number;
  };
}

export interface ResizeEvent extends ReplayEvent {
  type: 'resize';
  data: {
    width: number;
    height: number;
  };
}

// ─────────────────────────────────────────────────────────────────────────────
// Session Replay Document (stored in Cosmos)
// ─────────────────────────────────────────────────────────────────────────────

export interface SessionReplayDoc {
  id: string;
  pk: string; // Composite: `${productId}:${sessionId}`
  sessionId: string;
  productId: string;

  // Event data
  events: ReplayEvent[];
  eventCount: number;

  // Metadata
  startTimestamp: string;
  endTimestamp?: string;
  durationMs: number;

  // Privacy settings
  privacyConfig: {
    maskInputs: boolean;
    maskAllInputs: boolean; // If true, all input values are masked
    unmaskInputs: string[]; // CSS selectors for inputs to NOT mask
    blockSelector: string; // CSS selector for elements to completely block (e.g., password fields)
    ignoreSelector: string; // CSS selector for elements to ignore
  };

  // Storage
  createdAt: string;
  updatedAt: string;
  ttl: number; // Auto-expiry (default 7 days)
}

// ─────────────────────────────────────────────────────────────────────────────
// Replay Configuration
// ─────────────────────────────────────────────────────────────────────────────

export interface ReplayConfig {
  enabled: boolean;
  sampleRate: number; // 0-1, percentage of sessions to capture
  maxDurationMinutes: number;
  maxEvents: number;

  // Privacy settings
  privacy: {
    maskInputs: boolean;
    maskAllInputs: boolean;
    unmaskInputs: string[];
    blockSelector: string;
    ignoreSelector: string;
  };

  // Performance
  throttleMouse: number; // Minimum ms between mouse move events
  throttleScroll: number; // Minimum ms between scroll events
  inlineStylesheet: boolean; // Inline stylesheets for accurate replay
  recordCanvas: boolean; // Experimental: record canvas operations
}

// ─────────────────────────────────────────────────────────────────────────────
// Input Schemas
// ─────────────────────────────────────────────────────────────────────────────

export const ReplayEventSchema = z.object({
  id: z.string(),
  sessionId: z.string(),
  timestamp: z.number(),
  type: ReplayEventTypeEnum,
  data: z.record(z.unknown()),
});

export const IngestReplayEventsSchema = z.object({
  sessionId: z.string(),
  events: z.array(ReplayEventSchema).max(100),
  startTimestamp: z.string().datetime(),
  privacyConfig: z.object({
    maskInputs: z.boolean(),
    maskAllInputs: z.boolean(),
    unmaskInputs: z.array(z.string()),
    blockSelector: z.string(),
    ignoreSelector: z.string(),
  }),
});

export const QueryReplaySchema = z.object({
  limit: z.coerce.number().min(1).max(500).default(100),
  continuationToken: z.string().optional(),
});

export type IngestReplayEventsInput = z.infer<typeof IngestReplayEventsSchema>;
export type QueryReplayInput = z.infer<typeof QueryReplaySchema>;

// ─────────────────────────────────────────────────────────────────────────────
// Client SDK Types
// ─────────────────────────────────────────────────────────────────────────────

export interface ReplayRecorder {
  start(): void;
  stop(): void;
  pause(): void;
  resume(): void;
  isRecording(): boolean;
  getEvents(): ReplayEvent[];
  clear(): void;
}

// Configuration for client SDK
export interface ReplayRecorderConfig {
  sessionId: string;
  productId: string;
  apiEndpoint: string;
  flushIntervalMs: number;
  maxBufferSize: number;
  privacy: ReplayConfig['privacy'];
}
