import type {
  AgentStep,
  ChangeProposal,
  ChatMessage,
  CaptureProposal,
  DependencyEdge,
  DirectiveRecord,
  GiteaIssue,
  GiteaMilestone,
  IssueChange,
  LabelPlan,
  LifecycleEvent,
  ProposedIssue,
} from '@commitea/core'

/** The result of a write through the bridge. */
export type ApplyChangeResult =
  | { ok: false; reason: 'unconfigured' }
  | { ok: true; plan: LabelPlan; issue: GiteaIssue }

/** The result of filing captured issues. */
export type CreateIssuesResult =
  | { ok: false; reason: 'unconfigured' }
  | { ok: true; created: { number: number; title: string }[] }

/** The result of a capture_work decomposition. */
export type CaptureResult =
  | { ok: false; reason: 'unconfigured' | 'error'; message?: string }
  | ({ ok: true } & CaptureProposal)

/** A reconciled snapshot as it crosses the bridge. */
export interface SnapshotPayload {
  configured: boolean
  issues: GiteaIssue[]
  milestones: GiteaMilestone[]
  deps: DependencyEdge[]
  /** Normalized lifecycle events keyed by issue number. */
  timelines: Record<number, LifecycleEvent[]>
  /** true when served from the persisted cache (offline / instant boot). */
  stale?: boolean
  /** ISO time the persisted snapshot was reconciled (present on cached reads). */
  savedAt?: string
}

/** Boot payload — the persisted snapshot, or a marker that there's none yet. */
export type BootPayload =
  | { configured: false }
  | { configured: true; cached: false }
  | ({ configured: true; cached: true } & Omit<SnapshotPayload, 'configured'>)

/** The gitea bridge exposed by the preload over IPC (main-process backed). */
export interface GiteaBridge {
  status(): Promise<{ configured: boolean; repo: string | null }>
  boot(): Promise<BootPayload>
  reconcile(): Promise<SnapshotPayload>
  getIssue(index: number): Promise<GiteaIssue | null>
  applyChange(change: IssueChange): Promise<ApplyChangeResult>
  createIssues(issues: ProposedIssue[]): Promise<CreateIssuesResult>
}

/** One agent turn's result. */
export type ChatResult =
  | { ok: false; reason: 'unconfigured' | 'error'; message?: string }
  | { ok: true; content: string; steps: AgentStep[]; proposals: ChangeProposal[] }

/** The model bridge (Reginald) exposed by the preload over IPC. */
export interface ModelBridge {
  status(): Promise<{ configured: boolean; model: string | null }>
  chat(messages: ChatMessage[]): Promise<ChatResult>
  capture(braindump: string): Promise<CaptureResult>
}

/** The result of reading the directive ledger. */
export type DirectivesResult =
  | { ok: false; reason: 'unconfigured' | 'error'; message?: string }
  | { ok: true; directives: DirectiveRecord[] }

/** The pm-state bridge (machine-derived state) exposed by the preload over IPC. */
export interface PmStateBridge {
  directives(): Promise<DirectivesResult>
}

declare global {
  interface Window {
    commitea: {
      platform: string
      gitea: GiteaBridge
      model: ModelBridge
      pmstate: PmStateBridge
    }
  }
}
