/**
 * EventSchemaRegistry — V1.0.0 Alpha event schema registry
 *
 * Registers all 55 durable + 7 ephemeral event types from event-registry-v1.md §3-§4.
 * Implements: register, validate, list, get_schema methods.
 *
 * @module packages/runtime/src/events/EventSchemaRegistry
 */

import type { JsonObject } from '@aircoding/contracts'

// =============================================================================
// Types
// =============================================================================

export type EventPersistence = 'durable' | 'ephemeral'

export interface EventSchema {
  type: string
  version: number
  persistence: EventPersistence
  payload_schema: JsonObject
}

export interface RegisteredEvent {
  type: string
  version: number
  persistence: EventPersistence
  schema: JsonObject
}

// =============================================================================
// Event Registry Data — seeded from event-registry-v1.md §3 (durable) and §4 (ephemeral)
// =============================================================================

/** All 55 durable event types from event-registry-v1.md §3 */
const DURABLE_EVENTS: RegisteredEvent[] = [
  // §3.1 Session Events
  { type: 'session.created', version: 1, persistence: 'durable', schema: { session_id: '', project_id: '', project_root: '', title: '', model_provider_id: '', model_id: '', metadata: {} } },
  { type: 'session.archived', version: 1, persistence: 'durable', schema: { session_id: '', reason: '' } },
  { type: 'session.deleted', version: 1, persistence: 'durable', schema: { session_id: '', reason: '' } },

  // §3.2 Message Events
  { type: 'user.message.created', version: 1, persistence: 'durable', schema: { message_id: '', canonical_format: '', content_json: {}, parent_message_id: '', token_estimate: 0, metadata: {} } },
  { type: 'assistant.message.started', version: 1, persistence: 'durable', schema: { message_id: '', canonical_format: '', parent_message_id: '', route: [], metadata: {} } },
  { type: 'assistant.message.created', version: 1, persistence: 'durable', schema: { message_id: '', canonical_format: '', content_json: {}, parent_message_id: '', route: [], token_estimate: 0, metadata: {} } },
  { type: 'assistant.message.failed', version: 1, persistence: 'durable', schema: { message_id: '', partial_content_json: {}, error: {}, evidence_refs: [], metadata: {} } },

  // §3.3 Agent Events
  { type: 'agent.started', version: 1, persistence: 'durable', schema: { agent_id: '', agent_type: '', task_id: '', pid: 0, model_provider_id: '', model_id: '', workspace_id: '', metadata: {} } },
  { type: 'agent.completed', version: 1, persistence: 'durable', schema: { agent_id: '', task_id: '', summary: '', worker_result_ref: '', metadata: {} } },
  { type: 'agent.failed', version: 1, persistence: 'durable', schema: { agent_id: '', task_id: '', error: {}, evidence_refs: [], metadata: {} } },
  { type: 'agent.lost', version: 1, persistence: 'durable', schema: { agent_id: '', task_id: '', last_heartbeat_at: '', detection_reason: '' } },
  { type: 'agent.cancelled', version: 1, persistence: 'durable', schema: { agent_id: '', task_id: '', reason: '' } },

  // §3.4 Task Events
  { type: 'task.created', version: 1, persistence: 'durable', schema: { task_id: '', type: '', title: '', task_spec_json: {}, dependencies: [], metadata: {} } },
  { type: 'task.started', version: 1, persistence: 'durable', schema: { task_id: '', agent_id: '', attempt_id: '', attempt_index: 0, workspace_id: '' } },
  { type: 'task.completed', version: 1, persistence: 'durable', schema: { task_id: '', agent_id: '', attempt_id: '', worker_result_json: {}, summary: '', changed_files: [], evidence_refs: [] } },
  { type: 'task.blocked', version: 1, persistence: 'durable', schema: { task_id: '', agent_id: '', reason: '', blocker_kind: '', evidence_refs: [], suggested_next_step: '' } },
  { type: 'task.failed', version: 1, persistence: 'durable', schema: { task_id: '', agent_id: '', attempt_id: '', error: {}, evidence_refs: [], metadata: {} } },
  { type: 'task.cancelled', version: 1, persistence: 'durable', schema: { task_id: '', reason: '', cancelled_by: '' } },
  { type: 'task.interrupted', version: 1, persistence: 'durable', schema: { task_id: '', reason: '', resumable: false, resume_ref: '' } },

  // §3.5 Tool Events
  { type: 'tool.started', version: 1, persistence: 'durable', schema: { tool_run_id: '', tool_name: '', task_id: '', agent_id: '', origin_message_id: '', input_json: {}, metadata: {} } },
  { type: 'tool.completed', version: 1, persistence: 'durable', schema: { tool_run_id: '', output_json: {}, duration_ms: 0, artifact_ids: [], evidence_refs: [], metadata: {} } },
  { type: 'tool.failed', version: 1, persistence: 'durable', schema: { tool_run_id: '', duration_ms: 0, error: {}, evidence_refs: [], metadata: {} } },
  { type: 'tool.cancelled', version: 1, persistence: 'durable', schema: { tool_run_id: '', reason: '' } },

  // §3.6 Command Events
  { type: 'command.started', version: 1, persistence: 'durable', schema: { command_run_id: '', task_id: '', agent_id: '', origin_message_id: '', tool_run_id: '', command: '', cwd: '', metadata: {} } },
  { type: 'command.completed', version: 1, persistence: 'durable', schema: { command_run_id: '', exit_code: 0, duration_ms: 0, stdout_artifact_id: '', stderr_artifact_id: '', combined_artifact_id: '', diagnostic_ids: [], parsed_diagnostics_json: {}, metadata: {} } },
  { type: 'command.failed', version: 1, persistence: 'durable', schema: { command_run_id: '', exit_code: 0, duration_ms: 0, stdout_artifact_id: '', stderr_artifact_id: '', combined_artifact_id: '', error: {}, evidence_refs: [], metadata: {} } },

  // §3.7 Artifact, Diagnostic, Evidence Events
  { type: 'artifact.created', version: 1, persistence: 'durable', schema: { artifact_id: '', type: '', uri: '', path: '', original_name: '', size_bytes: 0, sha256: '', task_id: '', agent_id: '', tool_run_id: '', command_run_id: '', associated_entity_type: '', associated_entity_id: '', metadata: {} } },
  { type: 'diagnostic.created', version: 1, persistence: 'durable', schema: { diagnostic_id: '', task_id: '', agent_id: '', command_run_id: '', artifact_id: '', language: '', toolchain: '', severity: '', file: '', line: 0, column: 0, code: '', message: '', semantic_signature: '', metadata: {} } },
  { type: 'evidence.created', version: 1, persistence: 'durable', schema: { evidence_ref_id: '', kind: '', ref: '', location_json: {}, claim: '', task_id: '', agent_id: '', tool_run_id: '', command_run_id: '', artifact_id: '', diagnostic_id: '', message_id: '' } },

  // §3.8 Context and Summary Events
  { type: 'context.compaction.requested', version: 1, persistence: 'durable', schema: { reason: '', range_start_message_id: '', range_end_message_id: '', target_budget_tokens: 0 } },
  { type: 'context.compaction.started', version: 1, persistence: 'durable', schema: { task_id: '', agent_id: '', range_start_message_id: '', range_end_message_id: '' } },
  { type: 'context.compaction.completed', version: 1, persistence: 'durable', schema: { task_id: '', agent_id: '', summary_id: '', range_start_message_id: '', range_end_message_id: '', token_estimate_before: 0, token_estimate_after: 0 } },
  { type: 'context.compaction.failed', version: 1, persistence: 'durable', schema: { task_id: '', agent_id: '', range_start_message_id: '', range_end_message_id: '', error: {}, evidence_refs: [], metadata: {} } },
  { type: 'summary.created', version: 1, persistence: 'durable', schema: { summary_id: '', type: '', range_start_message_id: '', range_end_message_id: '', content_json: {}, metadata: {} } },

  // §3.9 Permission Events
  { type: 'permission.decision.recorded', version: 1, persistence: 'durable', schema: { decision_id: '', subject: '', action: '', grant_scope: '', reason: '', risk_level: '', decided_by: '', scope_json: {}, expires_at: '' } },
  { type: 'permission.prompt.requested', version: 1, persistence: 'durable', schema: { prompt_id: '', subject: '', risk_level: '', reason: '', options: [], default_option: '', request_ref: {} } },
  { type: 'permission.prompt.resolved', version: 1, persistence: 'durable', schema: { prompt_id: '', selected_option: '', decision_id: '', resolved_by: '' } },

  // §3.10 Doctor Events
  { type: 'doctor.run.started', version: 1, persistence: 'durable', schema: { run_id: '', mode: '', trigger: '' } },
  { type: 'doctor.issue.found', version: 1, persistence: 'durable', schema: { run_id: '', issue_id: '', severity: '', capability: '', dependency: '', message: '', fix_available: false, fix_requires_confirmation: false } },
  { type: 'doctor.fix.started', version: 1, persistence: 'durable', schema: { run_id: '', issue_id: '', fix_id: '', strategy: '' } },
  { type: 'doctor.fix.completed', version: 1, persistence: 'durable', schema: { run_id: '', issue_id: '', fix_id: '', evidence_refs: [] } },
  { type: 'doctor.fix.failed', version: 1, persistence: 'durable', schema: { run_id: '', issue_id: '', fix_id: '', error: {}, evidence_refs: [], metadata: {} } },
  { type: 'doctor.run.completed', version: 1, persistence: 'durable', schema: { run_id: '', status: '', issue_count: 0, blocking_issue_count: 0, report_artifact_id: '' } },

  // §3.11 Requirement and Architecture Events
  { type: 'requirement.changed', version: 1, persistence: 'durable', schema: { change_id: '', origin_message_id: '', summary: '', change_type: '', affected_refs: [] } },
  { type: 'architecture.plan.updated', version: 1, persistence: 'durable', schema: { plan_ref: '', update_kind: '', summary: '', affected_task_ids: [], adr_refs: [], c4_refs: [] } },
  { type: 'architecture.impact.completed', version: 1, persistence: 'durable', schema: { assessment_id: '', requirement_change_id: '', impact_level: '', decision: '', summary: '', affected_task_ids: [], evidence_refs: [] } },

  // §3.12 Workspace Events
  { type: 'workspace.created', version: 1, persistence: 'durable', schema: { workspace_id: '', task_id: '', agent_id: '', path: '', strategy: '', base_ref: '', branch_name: '' } },
  { type: 'workspace.merge.started', version: 1, persistence: 'durable', schema: { workspace_id: '', task_id: '', strategy: '', target_ref: '' } },
  { type: 'workspace.merge.completed', version: 1, persistence: 'durable', schema: { workspace_id: '', task_id: '', merged_ref: '', diff_artifact_id: '' } },
  { type: 'workspace.merge.conflicted', version: 1, persistence: 'durable', schema: { workspace_id: '', task_id: '', conflict_files: [], conflict_artifact_id: '', suggested_resolution: '' } },
  { type: 'workspace.cleaned', version: 1, persistence: 'durable', schema: { workspace_id: '', reason: '' } },

  // §3.13 Memory and Debug Knowledge Events
  { type: 'memory.candidate.created', version: 1, persistence: 'durable', schema: { candidate_id: '', source_ref: {}, memory_type: '', summary: '', evidence_refs: [] } },
  { type: 'memory.promoted', version: 1, persistence: 'durable', schema: { candidate_id: '', target_ref: '', promoted_by: '', summary: '' } },
  { type: 'memory.archived', version: 1, persistence: 'durable', schema: { candidate_id: '', memory_ref: '', reason: '' } },
  { type: 'debug.record.created', version: 1, persistence: 'durable', schema: { debug_record_id: '', task_id: '', failure_signature: '', summary: '', evidence_refs: [], verification_refs: [] } },
]

/** All 7 ephemeral event types from event-registry-v1.md §4 */
const EPHEMERAL_EVENTS: RegisteredEvent[] = [
  { type: 'agent.heartbeat', version: 1, persistence: 'ephemeral', schema: { agent_id: '', task_id: '', status: '', progress_text: '', current_step: '', resource_snapshot: {} } },
  { type: 'task.progress', version: 1, persistence: 'ephemeral', schema: { task_id: '', agent_id: '', phase: '', progress_text: '', percent: 0 } },
  { type: 'assistant.message.delta', version: 1, persistence: 'ephemeral', schema: { message_id: '', delta: {}, sequence: 0 } },
  { type: 'tool.progress', version: 1, persistence: 'ephemeral', schema: { tool_run_id: '', message: '', progress_json: {} } },
  { type: 'command.stdout.delta', version: 1, persistence: 'ephemeral', schema: { command_run_id: '', chunk: '', sequence: 0, truncated: false } },
  { type: 'command.stderr.delta', version: 1, persistence: 'ephemeral', schema: { command_run_id: '', chunk: '', sequence: 0, truncated: false } },
  { type: 'hud.frame.rendered', version: 1, persistence: 'ephemeral', schema: { frame_id: '', duration_ms: 0, dropped_frame_count: 0 } },
]

// =============================================================================
// EventSchemaRegistry
// =============================================================================

/**
 * Event schema registry implementing registration, validation, and schema lookup
 * for all V1.0.0 Alpha event types (55 durable + 7 ephemeral).
 */
export class EventSchemaRegistry {
  private registry: Map<string, RegisteredEvent> = new Map()

  constructor() {
    this.seedDefaults()
  }

  /**
   * Seed the registry with all known event types from event-registry-v1.md.
   */
  private seedDefaults(): void {
    for (const event of DURABLE_EVENTS) {
      this.register(event.type, event.version, event.persistence, event.schema)
    }
    for (const event of EPHEMERAL_EVENTS) {
      this.register(event.type, event.version, event.persistence, event.schema)
    }
  }

  /**
   * Register a new event type schema.
   * @param type - Event type name (e.g., 'session.created')
   * @param version - Event schema version
   * @param persistence - 'durable' or 'ephemeral'
   * @param schema - JSON schema for the payload
   */
  register(type: string, version: number, persistence: EventPersistence, schema: JsonObject): void {
    const key = `${type}@v${version}`
    this.registry.set(key, { type, version, persistence, schema })
  }

  /**
   * Validate that an event type+version exists and its payload matches the schema.
   * For V1.0.0 Alpha, this is a structural check — all payload fields are optional
   * and we only verify the type is registered.
   *
   * @param type - Event type name
   * @param version - Event schema version
   * @param _payload - Event payload to validate (structural check only in V1)
   * @returns true if valid, false otherwise
   */
  validate(type: string, version: number, _payload: unknown): boolean {
    const key = `${type}@v${version}`
    return this.registry.has(key)
  }

  /**
   * List all registered event types with their versions.
   * @returns Array of { type, version } objects
   */
  list(): Array<{ type: string; version: number; persistence: EventPersistence }> {
    const result: Array<{ type: string; version: number; persistence: EventPersistence }> = []
    for (const event of this.registry.values()) {
      result.push({ type: event.type, version: event.version, persistence: event.persistence })
    }
    return result
  }

  /**
   * Get the schema for a specific event type and version.
   * @param type - Event type name
   * @param version - Event schema version
   * @returns The JSON schema or undefined if not found
   */
  get_schema(type: string, version: number): JsonObject | undefined {
    const key = `${type}@v${version}`
    const event = this.registry.get(key)
    return event?.schema
  }

  /**
   * Get the persistence policy for an event type.
   * @param type - Event type name
   * @param version - Event schema version
   * @returns The persistence policy or undefined if not registered
   */
  getPersistence(type: string, version: number): EventPersistence | undefined {
    const key = `${type}@v${version}`
    return this.registry.get(key)?.persistence
  }

  /**
   * Check if an event type is registered.
   * @param type - Event type name
   * @param version - Event schema version
   * @returns true if registered
   */
  isRegistered(type: string, version: number): boolean {
    const key = `${type}@v${version}`
    return this.registry.has(key)
  }
}

/**
 * Default singleton instance for global use.
 */
export const eventSchemaRegistry = new EventSchemaRegistry()