// ─── Core Export Format Interface ────────────────────────────────────────────

/**
 * Defines a data export format. Implement this to add custom formats.
 *
 * @template T - The expected shape of the data (defaults to unknown for safety)
 *
 * @example
 * const xmlFormat: ExportFormat<Record<string, unknown>> = {
 *   id: 'xml',
 *   label: 'XML',
 *   extension: 'xml',
 *   mimeType: 'application/xml',
 *   serialize: (data) => toXml(data),
 * }
 */
export interface ExportFormat<T = unknown> {
  /** Unique identifier used to reference this format in the `formats` prop */
  id: string
  /** Display label shown in the format selector tabs */
  label: string
  /** File extension appended to the filename on download (without leading dot) */
  extension: string
  /** MIME type used for the downloaded Blob */
  mimeType: string
  /**
   * Transform `data` into a string for clipboard copy or file download.
   * May throw — the component catches all errors and shows them inline.
   */
  serialize: (data: T) => string
}

export interface ExportPayload<TItem = unknown, TMeta = unknown> {
  items: TItem[]
  meta?: TMeta
}

export type ExportDataScope = "combined" | "items" | "meta"

// ─── Built-in Format IDs ──────────────────────────────────────────────────────

export type BuiltinFormatId = "json" | "yaml"

/** A format entry in the `formats` prop: either a builtin ID or a custom format object */
export type FormatEntry = BuiltinFormatId | ExportFormat

// ─── Component Props ──────────────────────────────────────────────────────────

export interface RacletteExportProps {
  /**
   * The data to export. Accepts any value: object, array, string, number, etc.
   * Each serializer handles edge cases gracefully.
   */
  data: ExportPayload

  /**
   * Base filename for downloads (no extension). Extension is appended automatically.
   * @default 'export'
   */
  filename?: string

  /**
   * Ordered list of formats to offer. Mix builtin IDs and custom ExportFormat objects.
   * This single prop controls both inclusion and order.
   * @default ['json', 'yaml']
   */
  formats?: FormatEntry[]

  /**
   * ID of the format that should be active when the popover opens.
   * Falls back to the first format in the list if not found.
   */
  defaultFormat?: string

  /**
   * Label for the default trigger button (only used when no default slot is provided).
   * @default 'Export'
   */
  buttonLabel?: string

  /**
   * Disables the trigger button and prevents the popover from opening.
   * @default false
   */
  disabled?: boolean

  /**
   * Whether the preview pane starts collapsed.
   * @default true
   */
  previewCollapsed?: boolean

  /**
   * Shows a scope switch inside the popover to choose whether to export:
   * - the combined payload object
   * - only items
   * - only meta
   * @default true
   */
  showDataScopeSwitch?: boolean
}

// ─── Component Emits ──────────────────────────────────────────────────────────

export interface ExportSuccessPayload {
  /** ID of the format that was used */
  formatId: string
  /** Whether the user copied or downloaded */
  action: "copy" | "download"
}

export interface ExportErrorPayload {
  /** ID of the format that failed */
  formatId: string
  /** Whether the copy or download was attempted */
  action: "copy" | "download" | "serialize"
  /** The caught error */
  error: unknown
}

export interface RacletteExportEmits {
  (e: "export-success", payload: ExportSuccessPayload): void
  (e: "export-error", payload: ExportErrorPayload): void
}

// ─── Slot Props ───────────────────────────────────────────────────────────────

export interface TriggerSlotProps {
  /** Opens the export popover */
  open: () => void
  /** Whether the popover is currently open */
  isOpen: boolean
  /** Mirrors the `disabled` prop */
  disabled: boolean
  /** Vuetify activator props for custom trigger controls */
  menuProps?: Record<string, unknown>
}

// ─── Serialization Result ─────────────────────────────────────────────────────

export type SerializeResult =
  | { ok: true; value: string }
  | { ok: false; error: string }
