import { useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '@/api/client';
import { keys } from '@/api/workflows';
import type { Workflow, WorkflowGraph } from '@/types';

/**
 * Describe a workflow; get one back.
 *
 * Generating and creating are two calls on purpose. The first spends AI credit
 * and saves nothing, so a description that was misunderstood costs a look
 * rather than a workflow in the list; the second is the author agreeing to what
 * they were shown.
 */

export interface GeneratedWorkflow {
  id: number;
  name: string;
  graph: WorkflowGraph;
  /** What the author still has to decide, in the model's words. */
  notes: string[];
  /** Settings deliberately left empty, so the editor can point at them. */
  setup: Array<{ node: string; field: string; message: string }>;
  errors: Array<{ code: string; message: string; field?: string }>;
  warnings: Array<{ code: string; message: string; field?: string }>;
  usage: { inputTokens: number; outputTokens: number };
}

export function useGenerateWorkflow() {
  return useMutation({
    mutationFn: async (input: { description: string; connection: number }): Promise<GeneratedWorkflow> =>
      (await api.post<GeneratedWorkflow>('/generate', { ...input, create: false })).data,
  });
}

/**
 * Keep what was generated: a workflow, then its graph.
 *
 * Two requests rather than one because that is what the workflow API already
 * offers, and because the graph goes through the same save path as anything
 * drawn by hand — the same validation, the same version history.
 */
export function useKeepGenerated() {
  const client = useQueryClient();

  return useMutation({
    mutationFn: async (input: { name: string; graph: WorkflowGraph }): Promise<number> => {
      const created = (await api.post<Workflow>('/workflows', { name: input.name })).data;

      await api.put<Workflow>(`/workflows/${created.id}`, { graph: input.graph });

      return created.id;
    },
    onSuccess: () => {
      void client.invalidateQueries({ queryKey: keys.workflows });
    },
  });
}

/** What came back from asking for a change. */
export interface RevisedWorkflow {
  graph: WorkflowGraph;
  /** What the model says it did, and anything it could not do. */
  summary: string;
  changes: { added: string[]; removed: string[]; configured: string[] };
  notes: string[];
  setup: Array<{ node: string; field: string; message: string }>;
  errors: Array<{ code: string; message: string; field?: string }>;
  warnings: Array<{ code: string; message: string; field?: string }>;
  usage: { inputTokens: number; outputTokens: number };
}

/**
 * Ask for a change to the graph on screen.
 *
 * The graph goes in the request rather than being read from the database,
 * because the author is changing what they are looking at — which may include
 * work they have not saved.
 */
export function useReviseWorkflow() {
  return useMutation({
    mutationFn: async (input: {
      graph: WorkflowGraph;
      instruction: string;
      connection: number;
    }): Promise<RevisedWorkflow> => (await api.post<RevisedWorkflow>('/revise', input)).data,
  });
}
