// Типы для обмена сообщениями между компонентами

export type MessageType =
  | 'REQUEST_PERMISSIONS'
  | 'PERMISSIONS_GRANTED'
  | 'PERMISSIONS_DENIED'
  | 'GET_VIDEO_BUFFER'
  | 'VIDEO_BUFFER_RESPONSE'
  | 'GET_RRWEB_EVENTS'
  | 'RRWEB_EVENTS_RESPONSE'
  | 'SAVE_ARCHIVE'
  | 'ARCHIVE_SAVED'
  | 'START_RECORDING'
  | 'STOP_RECORDING'
  | 'RECORDING_ERROR'
  | 'OFFSCREEN_READY';

// IN-05 fix: Message<T = unknown> instead of `T = any`. Call sites that
// access `(msg as Message).data` MUST narrow before use — `unknown`
// forces that discipline, which `any` silently bypassed (every
// downstream access was implicitly `any` and skipped type checking).
// The Message inbox in src/background/index.ts and src/offscreen/recorder.ts
// already destructure via `msg.type` switch and never read `.data`
// directly, so the migration was safe (no widening needed).
export interface Message<T = unknown> {
  type: MessageType;
  data?: T;
  tabId?: number;
}

// Типы сообщений в long-lived port (offscreen ↔ SW; D-17 / Plan 04 / D-13)
export type PortMessageType =
  | 'PING'
  | 'REQUEST_BUFFER'
  | 'BUFFER';

export interface PortMessage {
  type: PortMessageType;
  // Wire-format (D-12 base64 transfer + D-13 segment lifecycle):
  // segments travel as TransferredVideoSegment[] because
  // chrome.runtime.Port JSON-serializes payloads across extension
  // contexts and JSON.stringify(blob) === "{}" loses binary content.
  // Each entry is one self-contained ~10 s WebM segment (EBML header
  // + seed keyframe). The receive side reconstructs VideoSegment[]
  // via src/shared/binary.ts.
  segments?: TransferredVideoSegment[];
}

// In-memory segment shape used by mergeVideoSegments after the SW
// decodes the wire format. Под D-13 каждый сегмент — самодостаточный
// WebM-блок ≈ 10 секунд (свой EBML-заголовок и стартовый keyframe).
export interface VideoSegment {
  data: Blob;
  timestamp: number;
}

// Wire-format for video segments traveling across the offscreen↔SW
// chrome.runtime.Port boundary. Replaces the previous Blob payload,
// which failed because Blob is not JSON-serializable.
// See debug session d12-blob-port-transfer-fails (resolved) and the
// GREEN block of tests/offscreen/port-serialization.test.ts for the
// pinned shape. The header-pin flag from the D-09..D-11 era is gone
// — under D-13 every segment IS implicitly its own header.
export interface TransferredVideoSegment {
  data: string;       // base64-encoded blob bytes (no data: prefix)
  type: string;       // MIME type to apply when reconstructing the Blob
  timestamp: number;
}

// Лог событий пользователя
// IN-05-companion: `meta` uses `unknown` values instead of `any`. The
// field carries free-form diagnostic data (HTTP status, stack frames,
// XHR method, etc.); none of the SW consumers READ from meta — it
// only flows from content script → archive JSON. `unknown` documents
// "treat me opaquely" honestly; `any` silently allowed any access.
export interface UserEvent {
  timestamp: number;
  type: 'click' | 'input' | 'navigation' | 'js_error' | 'network_error';
  target: string;
  value?: string;
  url: string;
  meta?: Record<string, unknown>;
}

// Метаданные сессии
export interface SessionMetadata {
  timestamp: string;
  url: string;
  userAgent: string;
  extensionVersion: string;
  videoBufferSeconds: number;
  logDurationMinutes: number;
  totalEvents: number;
}

// Сообщения для popup
export interface PopupState {
  isRecording: boolean;
  hasPermissions: boolean;
  status: 'idle' | 'saving' | 'done';
}

// Ответы от Service Worker
export interface VideoBufferResponse {
  segments: VideoSegment[];
}

// IN-05-companion: `events: unknown[]` instead of `any[]`. The events
// array carries rrweb's `EventWithTime` shape which is too large to
// import here without pulling rrweb into the shared module; the
// consumers (background/index.ts) already type it as `unknown[]` and
// pass through to JSZip. `any[]` would have silently bypassed all
// downstream type-checking.
export interface RrwebEventsResponse {
  events: unknown[];
}
