// File: src/types/reasoning.ts
import { Schema } from "effect";
import { ReasoningStepSchema } from "./step.js";

// ─── Reasoning Strategy ───
// Canonical definition lives in @reactive-agents/core.
// Re-export here so downstream reasoning code can import from either package.
import { ReasoningStrategy } from "@reactive-agents/core";
export { ReasoningStrategy };

// ─── Result Status ───

export const ReasoningStatus = Schema.Literal("completed", "failed", "partial");
export type ReasoningStatus = typeof ReasoningStatus.Type;

// ─── Reasoning Metadata ───

export const ReasoningMetadataSchema = Schema.Struct({
  duration: Schema.Number, // ms
  cost: Schema.Number, // USD
  tokensUsed: Schema.Number,
  /** Cumulative prompt tokens (optional — providers/strategies may not split). */
  inputTokens: Schema.optional(Schema.Number),
  /** Cumulative completion tokens (optional — providers/strategies may not split). */
  outputTokens: Schema.optional(Schema.Number),
  stepsCount: Schema.Number,
  confidence: Schema.Number, // 0-1
  effectiveness: Schema.optional(Schema.Number), // 0-1 (learned)
  selectedStrategy: Schema.optional(ReasoningStrategy), // for adaptive
});
export type ReasoningMetadata = typeof ReasoningMetadataSchema.Type;

// ─── Reasoning Result ───

export const ReasoningResultSchema = Schema.Struct({
  strategy: ReasoningStrategy,
  steps: Schema.Array(ReasoningStepSchema),
  output: Schema.Unknown,
  metadata: ReasoningMetadataSchema,
  status: ReasoningStatus,
  /**
   * Failure detail carried up from the kernel's final failed state (e.g. the
   * `explainProviderError`-enriched "LLM stream failed at iteration N: <provider
   * 413/400 …>" message). Present only on failed/error results; lets the runtime
   * surface the real cause instead of a generic "Reasoning failed".
   */
  error: Schema.optional(Schema.String),
});
export type ReasoningResult = typeof ReasoningResultSchema.Type;

// ─── Selection Context ───

export const SelectionContextSchema = Schema.Struct({
  taskDescription: Schema.String,
  taskType: Schema.String,
  complexity: Schema.Number, // 0-1
  urgency: Schema.Number, // 0-1
  costBudget: Schema.optional(Schema.Number),
  timeConstraint: Schema.optional(Schema.Number), // ms
  preferredStrategy: Schema.optional(ReasoningStrategy),
});
export type SelectionContext = typeof SelectionContextSchema.Type;
