// contracts §12 + §21 — Tool Contracts + Diagnostic Contracts
// File: tool.ts — ToolCategory, ToolDefinition, ToolExecutor, StreamingToolExecutor,
// ToolExecutionContext, ToolResultEnvelope, ToolEvent, ToolRegistry, Diagnostic
// Merged: diagnostics.ts symbols per DD §3

import type { JsonSchema, JsonObject, UUID, ISOTimeString, SessionID, ProjectID, TaskID, AgentID, MessageID, ArtifactID, EvidenceRefID, CommandRunID } from "./ids.js"
import type { AirError } from "./error.js"

// =============================================================================
// contracts §12 — Tool Contracts
// =============================================================================

export type ToolCategory =
  | "filesystem"
  | "shell"
  | "git"
  | "project"
  | "build"
  | "test"
  | "debug"
  | "static_analysis"
  | "gui"
  | "network"
  | "memory"
  | "context"
  | "artifact"
  | "permission"
  | "doctor"
  | "internal"

export interface ToolPermissionSpec {
  read_paths?: PathPolicy
  write_paths?: PathPolicy
  execute?: boolean
  network?: boolean
  system_sensitive?: boolean
  credentials?: boolean
}

export interface PathPolicy {
  allow?: string[]
  deny?: string[]
  source?: string
}

export interface ToolDefinition<I = unknown, O = unknown> {
  name: string
  version: number
  description: string
  input_schema: JsonSchema<I>
  output_schema: JsonSchema<O>
  category: ToolCategory
  permissions: ToolPermissionSpec
  streaming: boolean
}

export interface ToolExecutor<I = unknown, O = unknown> {
  execute(input: I, context: ToolExecutionContext): Promise<ToolResultEnvelope<O>>
}

export interface StreamingToolExecutor<I = unknown, O = unknown> {
  execute_streaming(input: I, context: ToolExecutionContext): AsyncIterable<ToolEvent>
  execute_final(input: I, context: ToolExecutionContext): Promise<ToolResultEnvelope<O>>
}

export interface ToolExecutionContext {
  session_id: SessionID
  project_id: ProjectID
  task_id?: TaskID
  agent_id?: AgentID
  origin_message_id?: MessageID
  permission_template: string
  cwd?: string
}

export interface ToolResultEnvelope<T = unknown> {
  status: "ok" | "error" | "cancelled"
  output?: T
  error?: AirError
  artifact_ids?: ArtifactID[]
  evidence_ref_ids?: EvidenceRefID[]
  metadata?: JsonObject
}

export interface ToolEvent {
  type: "progress" | "artifact" | "result"
  payload: unknown
}

export interface ToolRegistry {
  register<I, O>(definition: ToolDefinition<I, O>, executor: ToolExecutor<I, O>): void
  register_streaming<I, O>(definition: ToolDefinition<I, O>, executor: StreamingToolExecutor<I, O>): void
  call<I, O>(name: string, input: I, context: ToolExecutionContext): Promise<ToolResultEnvelope<O>>
  call_streaming<I, O>(name: string, input: I, context: ToolExecutionContext): AsyncIterable<ToolEvent | ToolResultEnvelope<O>>
  list(): ToolDefinition[]
}

// =============================================================================
// contracts §21 — Diagnostic Contracts
// =============================================================================

export type DiagnosticSeverity = "error" | "warning" | "info" | "hint"

export interface Diagnostic {
  diagnostic_id: UUID
  task_id?: TaskID
  agent_id?: AgentID
  command_run_id?: CommandRunID
  artifact_id?: ArtifactID
  language?: string
  toolchain?: string
  severity: DiagnosticSeverity
  file?: string
  line?: number
  column?: number
  code?: string
  message: string
  semantic_signature: string
  created_at: ISOTimeString
  metadata_json?: JsonObject
}