/**
 * 노드 기반 데이터 제어 시스템 타입 정의
 */

import { Node as ReactFlowNode, Edge as ReactFlowEdge } from "reactflow";

// ============================================================================
// 기본 노드 타입
// ============================================================================

export type NodeType =
  | "tableSource" // 테이블 소스
  | "externalDBSource" // 외부 DB 소스
  | "restAPISource" // REST API 소스
  | "condition" // 조건 분기
  | "dataTransform" // 데이터 변환
  | "aggregate" // 집계 노드 (SUM, COUNT, AVG 등)
  | "formulaTransform" // 수식 변환 노드
  | "insertAction" // INSERT 액션
  | "updateAction" // UPDATE 액션
  | "deleteAction" // DELETE 액션
  | "upsertAction" // UPSERT 액션
  | "emailAction" // 메일 발송 액션
  | "scriptAction" // 스크립트 실행 액션
  | "httpRequestAction" // HTTP 요청 액션
  | "procedureCallAction" // 프로시저/함수 호출 액션
  | "comment" // 주석
  | "log"; // 로그

// ============================================================================
// 타겟 타입 (액션 노드용)
// ============================================================================

export type TargetType = "internal" | "external" | "api";

// API 인증 타입
export type ApiAuthType = "none" | "basic" | "bearer" | "apikey";

// API 인증 설정
export interface ApiAuthConfig {
  username?: string;
  password?: string;
  token?: string;
  apiKey?: string;
  apiKeyHeader?: string; // 기본값: "X-API-Key"
}

// ============================================================================
// 필드 정의
// ============================================================================

export interface FieldDefinition {
  name: string;
  type: string;
  nullable: boolean;
  primaryKey?: boolean;
  label?: string;
  displayName?: string;
}

// ============================================================================
// 노드 데이터 타입별 정의
// ============================================================================

// 테이블 소스 노드
export interface TableSourceNodeData {
  connectionId: number;
  tableName: string;
  schema?: string;
  fields: FieldDefinition[];
  filters?: Array<{
    field: string;
    operator: string;
    value: any;
  }>;
  displayName?: string;
}

// 외부 DB 소스 노드
export interface ExternalDBSourceNodeData {
  connectionId: number;
  connectionName: string;
  dbType: string;
  tableName: string;
  fields: FieldDefinition[];
  displayName?: string;
}

// REST API 소스 노드
export interface RestAPISourceNodeData {
  method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
  url: string;
  headers?: Record<string, string>;
  body?: any;
  responseFields: FieldDefinition[];
  displayName?: string;
  authentication?: {
    type: "none" | "bearer" | "basic" | "apikey";
    token?: string;
  };
  timeout?: number;
  responseMapping?: string;
}

// 조건 연산자 타입
export type ConditionOperator =
  | "EQUALS"
  | "NOT_EQUALS"
  | "GREATER_THAN"
  | "LESS_THAN"
  | "GREATER_THAN_OR_EQUAL"
  | "LESS_THAN_OR_EQUAL"
  | "LIKE"
  | "NOT_LIKE"
  | "IN"
  | "NOT_IN"
  | "IS_NULL"
  | "IS_NOT_NULL"
  | "EXISTS_IN" // 다른 테이블에 존재함
  | "NOT_EXISTS_IN"; // 다른 테이블에 존재하지 않음

// 조건 분기 노드
export interface ConditionNodeData {
  conditions: Array<{
    field: string;
    operator: ConditionOperator;
    value: any;
    valueType?: "static" | "field" | "target"; // 비교 값 타입 (target: DB 기존값 비교)
    // EXISTS_IN / NOT_EXISTS_IN 전용 필드
    lookupTable?: string; // 조회할 테이블명
    lookupTableLabel?: string; // 조회할 테이블 라벨
    lookupField?: string; // 조회할 테이블의 비교 필드
    lookupFieldLabel?: string; // 조회할 테이블의 비교 필드 라벨
  }>;
  logic: "AND" | "OR";
  displayName?: string;
  // 타겟 테이블 조회 (DB 기존값과 비교할 때 사용)
  targetLookup?: {
    tableName: string;
    tableLabel?: string;
    lookupKeys: Array<{
      sourceField: string; // 소스(폼) 데이터의 키 필드
      targetField: string; // 타겟(DB) 테이블의 키 필드
      sourceFieldLabel?: string;
    }>;
  };
}

// 필드 매핑 노드
export interface FieldMappingNodeData {
  mappings: Array<{
    id: string;
    sourceField: string | null;
    targetField: string;
    transform?: string;
    staticValue?: any;
  }>;
  displayName?: string;
}

// 데이터 변환 노드
export interface DataTransformNodeData {
  transformations: Array<{
    type:
      | "UPPERCASE"
      | "LOWERCASE"
      | "TRIM"
      | "CONCAT"
      | "SPLIT"
      | "REPLACE"
      | "CALCULATE"
      | "EXPLODE"
      | "CAST"
      | "FORMAT"
      | "JSON_EXTRACT"
      | "CUSTOM";
    sourceField?: string; // 소스 필드
    sourceFieldLabel?: string; // 소스 필드 라벨
    targetField?: string; // 타겟 필드 (선택, 비어있으면 소스 필드에 적용)
    targetFieldLabel?: string; // 타겟 필드 라벨
    expression?: string; // 표현식
    parameters?: Record<string, any>; // 추가 파라미터
    // EXPLODE 전용
    delimiter?: string; // 구분자 (예: ",")
    // CONCAT 전용
    sourceFields?: string[]; // 다중 소스 필드
    sourceFieldLabels?: string[]; // 다중 소스 필드 라벨
    separator?: string; // 구분자 (예: " ")
    // SPLIT 전용
    splitIndex?: number; // 분리 후 가져올 인덱스
    // REPLACE 전용
    searchValue?: string; // 찾을 문자열
    replaceValue?: string; // 바꿀 문자열
    // CAST 전용
    castType?: "string" | "number" | "boolean" | "date"; // 변환할 타입
  }>;
  displayName?: string;
}

// 집계 함수 타입
export type AggregateFunction = "SUM" | "COUNT" | "AVG" | "MIN" | "MAX" | "FIRST" | "LAST";

// ============================================================================
// 수식 변환 노드 (Formula Transform)
// ============================================================================

// 수식 타입
export type FormulaType = "arithmetic" | "function" | "condition" | "static";

// 수식 변환 노드 데이터
export interface FormulaTransformNodeData {
  displayName?: string;

  // 타겟 테이블 조회 설정 (기존 값 참조용 - UPSERT 시나리오)
  targetLookup?: {
    tableName: string; // 조회할 테이블명
    tableLabel?: string; // 테이블 라벨
    lookupKeys: Array<{
      // 조회 키 (source 필드와 매칭)
      sourceField: string; // 소스 필드명
      sourceFieldLabel?: string;
      targetField: string; // 타겟 테이블의 필드명
      targetFieldLabel?: string;
    }>;
  };

  // 변환 규칙들
  transformations: Array<{
    id: string; // 고유 ID
    outputField: string; // 출력 필드명
    outputFieldLabel?: string; // 출력 필드 라벨
    formulaType: FormulaType; // 수식 타입

    // 산술 연산 (formulaType === "arithmetic")
    arithmetic?: {
      leftOperand: {
        type: "source" | "target" | "static" | "result"; // 값 소스
        field?: string; // source.* 또는 target.* 필드
        fieldLabel?: string;
        value?: string | number; // 정적 값
        resultField?: string; // 이전 변환 결과 필드 참조
      };
      operator: "+" | "-" | "*" | "/" | "%"; // 연산자
      rightOperand: {
        type: "source" | "target" | "static" | "result";
        field?: string;
        fieldLabel?: string;
        value?: string | number;
        resultField?: string;
      };
      // 추가 연산 (다중 연산 지원: (left op right) op1 val1 op2 val2 ...)
      additionalOperations?: Array<{
        operator: "+" | "-" | "*" | "/" | "%";
        operand: {
          type: "source" | "target" | "static" | "result";
          field?: string;
          fieldLabel?: string;
          value?: string | number;
          resultField?: string;
        };
      }>;
    };

    // 함수 (formulaType === "function")
    function?: {
      name: "NOW" | "COALESCE" | "CONCAT" | "UPPER" | "LOWER" | "TRIM" | "ROUND" | "ABS" | "SUBSTRING";
      arguments: Array<{
        type: "source" | "target" | "static" | "result";
        field?: string;
        fieldLabel?: string;
        value?: string | number;
        resultField?: string;
      }>;
    };

    // 조건 (formulaType === "condition")
    condition?: {
      when: {
        leftOperand: {
          type: "source" | "target" | "static" | "result";
          field?: string;
          fieldLabel?: string;
          value?: string | number;
          resultField?: string;
        };
        operator: "=" | "!=" | ">" | "<" | ">=" | "<=" | "IS_NULL" | "IS_NOT_NULL";
        rightOperand?: {
          type: "source" | "target" | "static" | "result";
          field?: string;
          fieldLabel?: string;
          value?: string | number;
          resultField?: string;
        };
      };
      then: {
        type: "source" | "target" | "static" | "result";
        field?: string;
        fieldLabel?: string;
        value?: string | number;
        resultField?: string;
      };
      else: {
        type: "source" | "target" | "static" | "result";
        field?: string;
        fieldLabel?: string;
        value?: string | number;
        resultField?: string;
      };
    };

    // 정적 값 (formulaType === "static")
    staticValue?: string | number | boolean;
  }>;
}

// 집계 노드 데이터
export interface AggregateNodeData {
  displayName?: string;
  // 그룹 기준 컬럼들
  groupByFields: Array<{
    field: string; // 컬럼명
    fieldLabel?: string; // 라벨
  }>;
  // 집계 연산들
  aggregations: Array<{
    id: string; // 고유 ID
    sourceField: string; // 집계할 소스 필드
    sourceFieldLabel?: string; // 소스 필드 라벨
    function: AggregateFunction; // 집계 함수
    outputField: string; // 출력 필드명
    outputFieldLabel?: string; // 출력 필드 라벨
  }>;
  // 집계 후 필터링 (HAVING 절)
  havingConditions?: Array<{
    field: string; // 집계 결과 필드
    operator: string; // 비교 연산자
    value: any; // 비교값
  }>;
}

// INSERT 액션 노드
export interface InsertActionNodeData {
  displayName?: string;

  // 🔥 타겟 타입 (새로 추가)
  targetType: TargetType; // "internal" | "external" | "api"

  // === 내부 DB 타겟 (targetType === "internal") ===
  targetConnection?: number;
  targetTable?: string;
  targetTableLabel?: string;

  // === 외부 DB 타겟 (targetType === "external") ===
  externalConnectionId?: number;
  externalConnectionName?: string;
  externalDbType?: string;
  externalTargetTable?: string;
  externalTargetSchema?: string;

  // === REST API 타겟 (targetType === "api") ===
  apiEndpoint?: string;
  apiMethod?: "POST" | "PUT" | "PATCH" | "DELETE";
  apiAuthType?: ApiAuthType;
  apiAuthConfig?: ApiAuthConfig;
  apiHeaders?: Record<string, string>;
  apiBodyTemplate?: string; // JSON 템플릿

  // === 공통 필드 ===
  fieldMappings: Array<{
    sourceField: string | null;
    sourceFieldLabel?: string;
    targetField: string;
    targetFieldLabel?: string;
    staticValue?: any;
    // 🔥 값 생성 유형 추가
    valueType?: "source" | "static" | "autoGenerate"; // 소스 필드 / 고정값 / 자동 생성
    // 자동 생성 옵션 (valueType === "autoGenerate" 일 때)
    numberingRuleId?: string; // 채번 규칙 ID
    numberingRuleName?: string; // 채번 규칙명 (표시용)
  }>;
  options: {
    batchSize?: number;
    ignoreErrors?: boolean;
    ignoreDuplicates?: boolean;
  };
}

// UPDATE 액션 노드
export interface UpdateActionNodeData {
  displayName?: string;

  // 🔥 타겟 타입 (새로 추가)
  targetType: TargetType; // "internal" | "external" | "api"

  // === 내부 DB 타겟 (targetType === "internal") ===
  targetConnection?: number;
  targetTable?: string;
  targetTableLabel?: string;

  // === 외부 DB 타겟 (targetType === "external") ===
  externalConnectionId?: number;
  externalConnectionName?: string;
  externalDbType?: string;
  externalTargetTable?: string;
  externalTargetSchema?: string;

  // === REST API 타겟 (targetType === "api") ===
  apiEndpoint?: string;
  apiMethod?: "POST" | "PUT" | "PATCH" | "DELETE";
  apiAuthType?: ApiAuthType;
  apiAuthConfig?: ApiAuthConfig;
  apiHeaders?: Record<string, string>;
  apiBodyTemplate?: string; // JSON 템플릿

  // === 공통 필드 ===
  fieldMappings: Array<{
    sourceField: string | null;
    sourceFieldLabel?: string;
    targetField: string;
    targetFieldLabel?: string;
    staticValue?: any;
  }>;
  whereConditions: Array<{
    field: string;
    fieldLabel?: string;
    operator: string;
    sourceField?: string;
    sourceFieldLabel?: string;
    staticValue?: any;
  }>;
  options: {
    batchSize?: number;
    ignoreErrors?: boolean;
  };
}

// DELETE 액션 노드
export interface DeleteActionNodeData {
  displayName?: string;

  // 🔥 타겟 타입 (새로 추가)
  targetType: TargetType; // "internal" | "external" | "api"

  // === 내부 DB 타겟 (targetType === "internal") ===
  targetConnection?: number;
  targetTable?: string;
  targetTableLabel?: string;

  // === 외부 DB 타겟 (targetType === "external") ===
  externalConnectionId?: number;
  externalConnectionName?: string;
  externalDbType?: string;
  externalTargetTable?: string;
  externalTargetSchema?: string;

  // === REST API 타겟 (targetType === "api") ===
  apiEndpoint?: string;
  apiMethod?: "POST" | "PUT" | "PATCH" | "DELETE";
  apiAuthType?: ApiAuthType;
  apiAuthConfig?: ApiAuthConfig;
  apiHeaders?: Record<string, string>;
  apiBodyTemplate?: string;

  // === 공통 필드 ===
  whereConditions: Array<{
    field: string;
    operator: string;
    sourceField?: string;
    staticValue?: any;
  }>;
  options: {
    requireConfirmation?: boolean;
  };
}

// UPSERT 액션 노드
export interface UpsertActionNodeData {
  displayName?: string;

  // 🔥 타겟 타입 (새로 추가)
  targetType: TargetType; // "internal" | "external" | "api"

  // === 내부 DB 타겟 (targetType === "internal") ===
  targetConnection?: number;
  targetTable?: string;
  targetTableLabel?: string;

  // === 외부 DB 타겟 (targetType === "external") ===
  externalConnectionId?: number;
  externalConnectionName?: string;
  externalDbType?: string;
  externalTargetTable?: string;
  externalTargetSchema?: string;

  // === REST API 타겟 (targetType === "api") ===
  apiEndpoint?: string;
  apiMethod?: "POST" | "PUT" | "PATCH" | "DELETE";
  apiAuthType?: ApiAuthType;
  apiAuthConfig?: ApiAuthConfig;
  apiHeaders?: Record<string, string>;
  apiBodyTemplate?: string;

  // === 공통 필드 ===
  conflictKeys: string[]; // ON CONFLICT 키
  conflictKeyLabels?: string[]; // 충돌 키 라벨
  fieldMappings: Array<{
    sourceField: string | null;
    sourceFieldLabel?: string;
    targetField: string;
    targetFieldLabel?: string;
    staticValue?: any;
  }>;
  options?: {
    batchSize?: number;
    updateOnConflict?: boolean;
  };
}

// 주석 노드
export interface CommentNodeData {
  content: string;
}

// 로그 노드
export interface LogNodeData {
  level: "debug" | "info" | "warn" | "error";
  message: string;
  includeData?: boolean;
}

// ============================================================================
// 외부 연동 액션 노드 (메일, 스크립트, HTTP 요청)
// ============================================================================

// 메일 발송 액션 노드
export interface EmailActionNodeData {
  displayName?: string;

  // 메일 계정 선택 (메일관리에서 등록한 계정)
  accountId?: string; // 메일 계정 ID (우선 사용)

  // 🆕 수신자 컴포넌트 사용 여부
  useRecipientComponent?: boolean; // true면 {{mailTo}}, {{mailCc}} 자동 사용
  recipientToField?: string; // 수신자 필드명 (기본: mailTo)
  recipientCcField?: string; // 참조 필드명 (기본: mailCc)

  // SMTP 서버 설정 (직접 설정 시 사용, accountId가 있으면 무시됨)
  smtpConfig?: {
    host: string;
    port: number;
    secure: boolean; // true = SSL/TLS
    auth?: {
      user: string;
      pass: string;
    };
  };

  // 메일 내용
  from?: string; // 발신자 이메일 (계정 선택 시 자동 설정)
  to: string; // 수신자 이메일 (쉼표로 구분하여 여러 명) - useRecipientComponent가 true면 무시됨
  cc?: string; // 참조 - useRecipientComponent가 true면 무시됨
  bcc?: string; // 숨은 참조
  subject: string; // 제목 (템플릿 변수 지원)
  body: string; // 본문 (템플릿 변수 지원)
  bodyType: "text" | "html"; // 본문 형식

  // 첨부파일 (선택)
  attachments?: Array<{
    filename: string;
    path?: string; // 파일 경로
    content?: string; // Base64 인코딩된 내용
  }>;

  // 고급 설정
  replyTo?: string;
  priority?: "high" | "normal" | "low";

  // 실행 옵션
  options?: {
    retryCount?: number;
    retryDelay?: number; // ms
    timeout?: number; // ms
  };
}

// 스크립트 실행 액션 노드
export interface ScriptActionNodeData {
  displayName?: string;

  // 스크립트 타입
  scriptType: "python" | "shell" | "powershell" | "node" | "executable";

  // 실행 방식
  executionMode: "inline" | "file";

  // 인라인 스크립트 (executionMode === "inline")
  inlineScript?: string;

  // 파일 경로 (executionMode === "file")
  scriptPath?: string;

  // 실행 파일 경로 (scriptType === "executable")
  executablePath?: string;

  // 명령줄 인자
  arguments?: string[];

  // 환경 변수
  environmentVariables?: Record<string, string>;

  // 입력 데이터 전달 방식
  inputMethod: "stdin" | "args" | "env" | "file";
  inputFormat?: "json" | "csv" | "text"; // stdin/file 사용 시

  // 작업 디렉토리
  workingDirectory?: string;

  // 실행 옵션
  options?: {
    timeout?: number; // ms (기본: 60000)
    maxBuffer?: number; // bytes (기본: 1MB)
    shell?: string; // 사용할 쉘 (예: /bin/bash)
    encoding?: string; // 출력 인코딩 (기본: utf8)
  };

  // 출력 처리
  outputHandling?: {
    captureStdout: boolean;
    captureStderr: boolean;
    parseOutput?: "json" | "lines" | "text";
    successExitCodes?: number[]; // 성공으로 간주할 종료 코드 (기본: [0])
  };
}

// HTTP 요청 액션 노드
export interface HttpRequestActionNodeData {
  displayName?: string;

  // 기본 설정
  url: string; // URL (템플릿 변수 지원)
  method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";

  // 헤더
  headers?: Record<string, string>;

  // 쿼리 파라미터
  queryParams?: Record<string, string>;

  // 요청 본문
  bodyType?: "none" | "json" | "form" | "text" | "binary";
  body?: string; // JSON 문자열 또는 텍스트 (템플릿 변수 지원)
  formData?: Array<{
    key: string;
    value: string;
    type: "text" | "file";
  }>;

  // 인증
  authentication?: {
    type: "none" | "basic" | "bearer" | "apikey" | "oauth2";
    // Basic Auth
    username?: string;
    password?: string;
    // Bearer Token
    token?: string;
    // API Key
    apiKey?: string;
    apiKeyName?: string;
    apiKeyLocation?: "header" | "query";
    // OAuth2 (향후 확장)
    oauth2Config?: {
      grantType: "client_credentials" | "password" | "authorization_code";
      tokenUrl: string;
      clientId: string;
      clientSecret: string;
      scope?: string;
    };
  };

  // 고급 설정
  options?: {
    timeout?: number; // ms (기본: 30000)
    followRedirects?: boolean; // 리다이렉트 따라가기 (기본: true)
    maxRedirects?: number; // 최대 리다이렉트 횟수 (기본: 5)
    validateStatus?: string; // 성공 상태 코드 범위 (예: "2xx", "200-299")
    retryCount?: number;
    retryDelay?: number; // ms
    retryOn?: ("timeout" | "5xx" | "network")[]; // 재시도 조건
  };

  // 응답 처리
  responseHandling?: {
    extractPath?: string; // JSON 경로 (예: "data.items")
    saveToVariable?: string; // 결과를 저장할 변수명
    validateSchema?: boolean; // JSON 스키마 검증
    expectedSchema?: object; // 예상 스키마
  };
}

// ============================================================================
// 프로시저/함수 호출 노드
// ============================================================================

export interface ProcedureCallActionNodeData {
  displayName?: string;

  dbSource: "internal" | "external";
  connectionId?: number;
  connectionName?: string;

  procedureName?: string;
  procedureSchema?: string;
  callType: "procedure" | "function";

  parameters?: {
    name: string;
    dataType: string;
    mode: "IN" | "OUT" | "INOUT";
    source: "record_field" | "static" | "step_variable";
    field?: string;
    value?: string;
  }[];
}

// ============================================================================
// 통합 노드 데이터 타입
// ============================================================================

export type NodeData =
  | TableSourceNodeData
  | ExternalDBSourceNodeData
  | RestAPISourceNodeData
  | ConditionNodeData
  | FieldMappingNodeData
  | DataTransformNodeData
  | AggregateNodeData
  | FormulaTransformNodeData
  | InsertActionNodeData
  | UpdateActionNodeData
  | DeleteActionNodeData
  | UpsertActionNodeData
  | EmailActionNodeData
  | ScriptActionNodeData
  | HttpRequestActionNodeData
  | ProcedureCallActionNodeData
  | CommentNodeData
  | LogNodeData;

// ============================================================================
// React Flow 노드 확장
// ============================================================================

export interface FlowNode extends ReactFlowNode {
  type: NodeType;
  data: NodeData & {
    // 공통 메타데이터
    validation?: {
      valid: boolean;
      errors?: string[];
      warnings?: string[];
    };
    // 실행 상태 (디버그 모드용)
    executionState?: {
      status: "pending" | "running" | "success" | "error" | "idle";
      progress?: number;
      processedCount?: number;
      errorMessage?: string;
    };
  };
}

// ============================================================================
// 엣지 타입
// ============================================================================

export type EdgeType =
  | "dataFlow" // 일반 데이터 흐름
  | "fieldConnection" // 필드 연결
  | "conditionalTrue" // 조건 TRUE
  | "conditionalFalse"; // 조건 FALSE

export interface FlowEdge extends Omit<ReactFlowEdge, 'type' | 'data'> {
  type?: EdgeType;
  data?: {
    dataType?: string;
    validation?: {
      valid: boolean;
      errors?: string[];
    };
    // 조건 분기용
    condition?: "TRUE" | "FALSE";
    // 필드 연결용
    sourceFieldName?: string;
    targetFieldName?: string;
  };
}

// ============================================================================
// 전체 플로우 데이터
// ============================================================================

export interface DataFlow {
  id?: number;
  name: string;
  description: string;
  companyCode: string;
  nodes: FlowNode[];
  edges: FlowEdge[];
  viewport?: {
    x: number;
    y: number;
    zoom: number;
  };
  metadata?: {
    createdAt?: string;
    updatedAt?: string;
    createdBy?: string;
    version?: number;
    tags?: string[];
  };
}

// ============================================================================
// 검증 결과
// ============================================================================

export interface ValidationResult {
  valid: boolean;
  errors: Array<{
    nodeId?: string;
    edgeId?: string;
    message: string;
    severity: "error" | "warning" | "info";
  }>;
}

// ============================================================================
// 실행 결과
// ============================================================================

export interface ExecutionResult {
  success: boolean;
  processedCount: number;
  errorCount: number;
  duration: number;
  nodeResults: Array<{
    nodeId: string;
    status: "success" | "error" | "skipped";
    processedCount?: number;
    errorMessage?: string;
  }>;
}

// ============================================================================
// 노드 팔레트 아이템
// ============================================================================

export interface NodePaletteItem {
  type: NodeType;
  label: string;
  icon: string;
  description: string;
  category: "source" | "transform" | "action" | "external" | "utility";
  color: string;
}

// ============================================================================
// 템플릿
// ============================================================================

export interface FlowTemplate {
  id: string;
  name: string;
  description: string;
  category: "builtin" | "custom";
  thumbnail?: string;
  nodes: FlowNode[];
  edges: FlowEdge[];
  parameters?: Array<{
    name: string;
    label: string;
    type: "string" | "number" | "select";
    defaultValue?: any;
    options?: Array<{ label: string; value: any }>;
  }>;
  tags?: string[];
}
