/**
 * useOracleExecution — manages prompt submission and durable execution history.
 */
import { useState, useCallback, useRef } from 'react';
import type { PromptExecution, CanvasComponent, PlacementMode } from '../types/canvas';
import { submitPrompt } from '../lib/oracleApiClient';

export interface ExecutionEntry {
  execution: PromptExecution;
  componentsCreated: string[];
}

export interface OracleExecutionState {
  history: ExecutionEntry[];
  inFlight: PromptExecution | null;
  lastError: string | null;
  submit: (params: {
    pageId: string;
    branchId: string;
    prompt: string;
    tenantId: string;
    actorId: string;
    placementMode?: PlacementMode;
    conversationContext?: Array<{ role: 'user' | 'assistant'; content: string }>;
    onExecutionCommitted?: (commit: {
      headRevision: number;
      components: CanvasComponent[];
      execution: PromptExecution;
    }) => void;
  }) => Promise<void>;
  clearError: () => void;
  resetHistory: () => void;
}

export function useOracleExecution(): OracleExecutionState {
  const [history, setHistory] = useState<ExecutionEntry[]>([]);
  const [inFlight, setInFlight] = useState<PromptExecution | null>(null);
  const [lastError, setLastError] = useState<string | null>(null);
  const requestIdRef = useRef(0);

  const submit = useCallback(
    async ({
      pageId,
      branchId,
      prompt,
      tenantId,
      actorId,
      placementMode = 'append_after_last_visible_component',
      conversationContext = [],
      onExecutionCommitted,
    }: {
      pageId: string;
      branchId: string;
      prompt: string;
      tenantId: string;
      actorId: string;
      placementMode?: PlacementMode;
      conversationContext?: Array<{ role: 'user' | 'assistant'; content: string }>;
      onExecutionCommitted?: (commit: {
        headRevision: number;
        components: CanvasComponent[];
        execution: PromptExecution;
      }) => void;
    }) => {
      const clientRequestId = `cli_${Date.now()}_${++requestIdRef.current}`;
      const now = new Date().toISOString();
      const optimistic: PromptExecution = {
        executionId: `pex_${clientRequestId}`,
        tenantId,
        pageId,
        branchId,
        actorId,
        prompt,
        intentClass: 'analytical',
        status: 'planning',
        modelRuntime: 'oracle_runtime',
        semanticModelVersion: 'oracle_semantic_v2026_04_08_01',
        warnings: [],
        createdAt: now,
      };

      setInFlight(optimistic);
      setLastError(null);

      try {
        setInFlight((prev) => (prev ? { ...prev, status: 'executing' } : prev));

        const response = await submitPrompt(pageId, {
          clientRequestId,
          branchId,
          prompt,
          conversationContext,
          placementMode,
        });

        const completed: PromptExecution = {
          ...optimistic,
          executionId: response.executionId,
          status: response.status,
          summary: response.summary,
          warnings: response.warnings,
          componentsCreated: response.componentsCreated,
          completedAt: new Date().toISOString(),
        };

        onExecutionCommitted?.({
          headRevision: response.headRevision,
          components: response.components,
          execution: completed,
        });

        setHistory((prev) => [...prev, { execution: completed, componentsCreated: response.componentsCreated }]);
        setInFlight(null);
      } catch (err) {
        const msg = err instanceof Error ? err.message : 'Prompt execution failed';
        const failed: PromptExecution = {
          ...optimistic,
          status: 'failed',
          warnings: [msg],
          completedAt: new Date().toISOString(),
        };
        setHistory((prev) => [...prev, { execution: failed, componentsCreated: [] }]);
        setInFlight(null);
        setLastError(msg);
      }
    },
    [],
  );

  return {
    history,
    inFlight,
    lastError,
    submit,
    clearError: () => setLastError(null),
    resetHistory: () => setHistory([]),
  };
}
