/**
 * Automation2 Flow Editor - Schema-based output preview builders.
 * Derives preview trees from portTypeCatalog + node outputPorts.
 */

import type { CanvasNode } from '../../editor/FlowCanvas';
import type { PortSchema, NodeType } from '../../../../api/workflowApi';

let _portTypeCatalog: Record<string, PortSchema> = {};

export function setPortTypeCatalog(catalog: Record<string, PortSchema>): void {
  _portTypeCatalog = catalog;
}

function _defaultForType(typeStr: string): unknown {
  if (typeStr.startsWith('List')) return [];
  if (typeStr.startsWith('Dict')) return {};
  if (typeStr === 'bool') return false;
  if (typeStr === 'int') return 0;
  if (typeStr === 'str') return '...';
  if (typeStr === 'Any') return '...';
  return null;
}

function _buildSchemaPreview(schemaName: string): Record<string, unknown> {
  const schema = _portTypeCatalog[schemaName];
  if (!schema || !schema.fields) return {};
  const result: Record<string, unknown> = {};
  for (const field of schema.fields) {
    result[field.name] = _defaultForType(field.type);
  }
  result._success = true;
  result._error = null;
  return result;
}

function _buildDynamicFormPreview(node: CanvasNode): Record<string, unknown> {
  const fields = (node.parameters?.fields ?? node.parameters?.formFields) as
    | Array<{ name?: string; type?: string }>
    | undefined;
  if (!Array.isArray(fields)) return { payload: {} };
  const payload: Record<string, unknown> = {};
  for (const f of fields) {
    if (f && typeof f === 'object' && f.name) {
      payload[f.name] = '';
    }
  }
  return { payload, _success: true, _error: null };
}

/** Build preview for a single node using its outputPorts schema */
export function buildNodeOutputPreview(
  node: CanvasNode,
  nodeTypeDef?: NodeType
): unknown {
  const outputPorts = nodeTypeDef?.outputPorts;
  if (!outputPorts) return {};

  const port0 = outputPorts[0];
  if (!port0) return {};

  if (port0.dynamic && port0.deriveFrom) {
    if (port0.schema === 'FormPayload') {
      return _buildDynamicFormPreview(node);
    }
  }

  if (port0.schema === 'Transit') {
    return { _transit: true, _meta: {}, data: {} };
  }

  return _buildSchemaPreview(port0.schema);
}

/** Build full nodeOutputsPreview map from graph */
export function buildNodeOutputsPreview(
  nodes: CanvasNode[],
  nodeTypes: NodeType[],
  nodeOutputsFromRun?: Record<string, unknown>
): Record<string, unknown> {
  const typeMap = new Map(nodeTypes.map((nt) => [nt.id, nt]));
  const result: Record<string, unknown> = {};
  for (const n of nodes) {
    const fromRun = nodeOutputsFromRun?.[n.id];
    if (fromRun !== undefined) {
      result[n.id] = fromRun;
    } else {
      result[n.id] = buildNodeOutputPreview(n, typeMap.get(n.type));
    }
  }
  return result;
}
