// Wire types for the Transmission RPC surface this sidecar uses.
//
// Field names are Transmission's OWN, verbatim — including its inconsistent casing (`percentDone` next to
// `begin_piece`, `peer-limit`, `sequential_download`). That is deliberate: renaming them would mean every
// future field needs a translation entry, and a name that doesn't appear in Transmission's rpc-spec.md is a
// name you cannot grep for when something misbehaves. The only fields we invent are the `officer*` derived
// ones at the bottom of Torrent, which are prefixed so they can never be mistaken for upstream data.

/** Transmission's torrent status enum (rpc-spec.md §3.3). */
export const TorrentStatus = {
  Stopped: 0,
  CheckWait: 1,
  Check: 2,
  DownloadWait: 3,
  Download: 4,
  SeedWait: 5,
  Seed: 6,
} as const;

export type TrackerStat = {
  announce: string;
  announceState: number;
  downloadCount: number;
  hasAnnounced: boolean;
  hasScraped: boolean;
  host: string;
  id: number;
  isBackup: boolean;
  lastAnnouncePeerCount: number;
  lastAnnounceResult: string;
  lastAnnounceSucceeded: boolean;
  lastAnnounceTime: number;
  lastScrapeResult: string;
  lastScrapeSucceeded: boolean;
  lastScrapeTime: number;
  leecherCount: number;
  nextAnnounceTime: number;
  scrape: string;
  seederCount: number;
  tier: number;
};

export type TorrentFile = {
  bytesCompleted: number;
  length: number;
  name: string;
};

export type TorrentFileStat = {
  bytesCompleted: number;
  priority: number;
  wanted: boolean;
};

export type TorrentPeer = {
  address: string;
  clientName: string;
  clientIsChoked: boolean;
  clientIsInterested: boolean;
  flagStr: string;
  isDownloadingFrom: boolean;
  isEncrypted: boolean;
  isIncoming: boolean;
  isUploadingTo: boolean;
  isUTP: boolean;
  peerIsChoked: boolean;
  peerIsInterested: boolean;
  port: number;
  progress: number;
  rateToClient: number;
  rateToPeer: number;
};

export type PeersFrom = {
  fromCache: number;
  fromDht: number;
  fromIncoming: number;
  fromLpd: number;
  fromLtep: number;
  fromPex: number;
  fromTracker: number;
};

export type Torrent = {
  id: number;
  name: string;
  status: number;
  totalSize: number;
  sizeWhenDone: number;
  leftUntilDone: number;
  haveValid: number;
  percentDone: number;
  metadataPercentComplete: number;
  recheckProgress?: number;
  downloadedEver: number;
  uploadedEver: number;
  corruptEver?: number;
  uploadRatio: number;
  rateDownload: number;
  rateUpload: number;
  eta: number;
  peersSendingToUs: number;
  peersGettingFromUs: number;
  addedDate: number;
  doneDate: number;
  activityDate: number;
  secondsSeeding: number;
  downloadDir: string;
  bandwidthPriority: number;
  queuePosition: number;
  isPrivate: boolean;
  labels: string[];
  error: number;
  errorString: string;
  pieceCount: number;
  pieceSize: number;
  magnetLink: string;
  group: string;
  'file-count': number;
  trackerStats: TrackerStat[];
  trackerList?: string;
  // Per-torrent limits — the fields the "Other settings" dialog reads and writes.
  honorsSessionLimits: boolean;
  downloadLimited: boolean;
  downloadLimit: number;
  uploadLimited: boolean;
  uploadLimit: number;
  'peer-limit': number;
  seedRatioMode: number;
  seedRatioLimit: number;
  seedIdleMode: number;
  seedIdleLimit: number;
  sequential_download?: boolean;
  // Detail-only fields — present when fetched through /_officer/torrents/:id.
  hashString?: string;
  comment?: string;
  creator?: string;
  dateCreated?: number;
  maxConnectedPeers?: number;
  files?: TorrentFile[];
  fileStats?: TorrentFileStat[];
  peers?: TorrentPeer[];
  peersFrom?: PeersFrom;
  // ── Derived by the sidecar, never sent by Transmission ──
  /**
   * The primary tracker's host with its port and any ignorable subdomain prefix stripped
   * (`udp://tr.example.org:1337/announce` → `example.org`). The UI groups by this, so the normalisation
   * has to be one implementation, not one per caller.
   */
  officerTrackerHost: string;
  /** Human-readable announce state of the primary tracker, for the "Tracker Status" column. */
  officerTrackerStatus: string;
  /** Count of trackers that have reported an error, so the UI can flag a torrent without walking the array. */
  officerTrackerErrors: number;
};

export type SessionSettings = Record<string, unknown> & {
  version: string;
  'rpc-version': number;
  'download-dir': string;
};

export type SessionStats = {
  activeTorrentCount: number;
  pausedTorrentCount: number;
  torrentCount: number;
  downloadSpeed: number;
  uploadSpeed: number;
  'cumulative-stats': StatsBucket;
  'current-stats': StatsBucket;
};

export type StatsBucket = {
  downloadedBytes: number;
  uploadedBytes: number;
  filesAdded: number;
  sessionCount: number;
  secondsActive: number;
};

/** The fields the torrent list needs. Mirrors what the list UI actually renders — nothing speculative. */
export const LIST_FIELDS = [
  'activityDate',
  'addedDate',
  'bandwidthPriority',
  'corruptEver',
  'doneDate',
  'downloadDir',
  'downloadedEver',
  'downloadLimit',
  'downloadLimited',
  'error',
  'errorString',
  'eta',
  'file-count',
  'group',
  'haveValid',
  'honorsSessionLimits',
  'id',
  'isPrivate',
  'labels',
  'leftUntilDone',
  'magnetLink',
  'metadataPercentComplete',
  'name',
  'peer-limit',
  'peersGettingFromUs',
  'peersSendingToUs',
  'percentDone',
  'pieceCount',
  'pieceSize',
  'queuePosition',
  'rateDownload',
  'rateUpload',
  'secondsSeeding',
  'seedIdleLimit',
  'seedIdleMode',
  'seedRatioLimit',
  'seedRatioMode',
  'sequential_download',
  'sizeWhenDone',
  'status',
  'totalSize',
  'trackerList',
  'trackerStats',
  'uploadedEver',
  'uploadLimit',
  'uploadLimited',
  'uploadRatio',
] as const;

/** Extra fields only the detail pane needs — big arrays we refuse to pull for every row on every poll. */
export const DETAIL_FIELDS = [
  'comment',
  'creator',
  'dateCreated',
  'fileStats',
  'files',
  'hashString',
  'maxConnectedPeers',
  'peers',
  'peersFrom',
  'recheckProgress',
] as const;
