export interface User {
  id: number
  email: string
  roles: string[]
  theme: string | null
  /** Opt-in design version — 'v1' (cream, original) or 'v2' (atmospheric dusks). */
  designVersion: 'v1' | 'v2'
  timezone: string
}

export type DeviceModel = 'v1' | 'v2'

/** Panel dimensions a device renders to for a given user orientation. */
export interface PanelDims {
  /** Pre-rotation source width — matches the renderer's thumbnail target. */
  width: number
  /** Pre-rotation source height. */
  height: number
}

/**
 * Crop / render dimensions for a device's photo at the user's chosen
 * orientation. Mirrors `DeviceModel::width(Orientation)` / `height(...)` on
 * the server. Keep these tables in sync.
 *
 *  - V1: native landscape 800×480 → upscaled to 1600×960 for better dither
 *  - V2: native portrait  1200×1600
 */
export function panelDims(model: DeviceModel, orientation: 'landscape' | 'portrait'): PanelDims {
  if (model === 'v1') {
    return orientation === 'landscape' ? { width: 1600, height: 960 } : { width: 960, height: 1600 }
  }
  // v2 — 13.3" Spectra-6, portrait-native
  return orientation === 'landscape' ? { width: 1600, height: 1200 } : { width: 1200, height: 1600 }
}

export interface Device {
  id: number
  mac: string
  name: string
  model: DeviceModel
  orientation: 'landscape' | 'portrait'
  rotationIntervalMinutes: number
  /** Wake times as minutes-since-midnight (0-1439). Empty = use rotationIntervalMinutes. */
  wakeTimes: number[]
  timezone: string
  uniquenessWindow: number
  rotationMode: 'random' | 'least_recently_shown' | 'oldest_upload' | 'newest_upload'
  prioritizeNeverShown: boolean
  linkedAt: string
  lastSeenAt: string | null
  /** Server-stamped expected next poll time. Drives the "next sync" label. */
  nextPollExpectedAt: string | null
  lockedImageId: number | null
  currentImageId: number | null
}

export interface CropParams {
  natX: number
  natY: number
  natW: number
  natH: number
}

export interface StickerLayer {
  id: string
  type: string
  x: number
  y: number
  scale: number
  rotation: number
  /** New stickers carry the emoji glyph directly; legacy stickers leave this
   *  blank and the renderer falls back to the STICKERS lookup by `type`. */
  emoji?: string
  /** Set for image-based stickers (e.g. 'santa-hat') that aren't representable
   *  as a single Unicode emoji. Mutually exclusive with `emoji`. */
  imageAsset?: string
}

export interface Image {
  id: number
  originalFilename: string
  thumbnailUrl: string
  originalUrl: string
  uploadedAt: string
  approvedDeviceIds: number[]
  cropParams: CropParams | null
  stickerState: StickerLayer[] | null
  cropOrientation: 'landscape' | 'portrait' | null
}

export interface RenderedAsset {
  id: number
  imageId: number
  deviceModel: string
  orientation: 'landscape' | 'portrait'
  status: 'pending' | 'processing' | 'ready' | 'failed'
}

export interface SharedImage {
  id: number
  imageId: number
  thumbnailUrl: string
  sharedBy: string
  sharedAt: string
  status: 'pending' | 'approved' | 'declined'
}

export interface SharedImagePage {
  items: SharedImage[]
  total: number
  page: number
  limit: number
  totalPages: number
}

export interface Token {
  uuid: string
  type: 'share_approve' | 'share_decline' | 'hard_delete_confirm'
  expiresAt: string
  usedAt: string | null
}

export interface ApiError {
  message: string
  errors?: Record<string, string[]>
}
