/**
 * Types for the gitea read client. Deliberately minimal: `@commitea/core` is
 * pure (no DOM lib, no Electron, no network), so we don't reach for the global
 * `fetch`/`Response`/`RequestInit` DOM types — we define the small structural
 * surface we actually use. The real `globalThis.fetch` is structurally
 * assignable to `FetchLike`, so the desktop main process passes it verbatim
 * while tests pass a stub.
 */

import type { LabelFacts } from '../labels/label-schema.js'

/** Connection config. `baseUrl` is the instance root (no `/api/v1`). */
export interface GiteaConfig {
  /** e.g. `https://gitea.stephenmann.io` — trailing slash tolerated. */
  baseUrl: string
  /** Personal access token (scopes: issue/repository/user). */
  token: string
  owner: string
  repo: string
}

export interface GiteaRequestInit {
  method?: string
  headers?: Record<string, string>
  body?: string
}

/** The slice of a `fetch` Response we consume. */
export interface GiteaHttpResponse {
  ok: boolean
  status: number
  json(): Promise<unknown>
  text(): Promise<string>
}

export type FetchLike = (url: string, init?: GiteaRequestInit) => Promise<GiteaHttpResponse>

/** Milestone as referenced from an issue (not the full milestone resource). */
export interface GiteaMilestoneRef {
  id: number
  title: string
  /** ISO date the milestone is due, or null. */
  dueOn: string | null
}

/** A milestone resource with its open/closed counts. */
export interface GiteaMilestone {
  id: number
  title: string
  description: string
  dueOn: string | null
  state: 'open' | 'closed'
  openIssues: number
  closedIssues: number
}

/**
 * Normalized issue — camelCase, label names flattened, scheduler-facing
 * `facts` precomputed via `extractLabelFacts`. This is the domain shape the
 * rest of CommiTea works with; raw gitea JSON never escapes this module.
 */
export interface GiteaIssue {
  number: number
  title: string
  body: string
  state: 'open' | 'closed'
  labels: string[]
  facts: LabelFacts
  milestone: GiteaMilestoneRef | null
  /** Primary assignee username, or null. */
  assignee: string | null
  /** All assignee usernames (includes the primary). */
  assignees: string[]
  createdAt: string
  updatedAt: string
  closedAt: string | null
  url: string
}

/** Thrown on a non-2xx gitea response; carries the status + raw body. */
export class GiteaApiError extends Error {
  constructor(
    readonly status: number,
    message: string,
    readonly body?: string,
  ) {
    super(message)
    this.name = 'GiteaApiError'
  }
}
