import { PrismaClient } from '@prisma/client';

export const NODE_TYPES = [
  // ─── TRIGGER ───────────────────────────────────────────────────────────────
  {
    type: 'cron_trigger',
    category: 'TRIGGER',
    label: 'Cron Trigger',
    icon: 'ClockCircleOutlined',
    description: 'Trigger workflow on a cron schedule',
    configSchema: {
      type: 'object',
      properties: {
        cron: {
          type: 'string',
          description: 'Cron expression (6-field with seconds supported)',
        },
        timezone: {
          type: 'string',
          description: 'IANA timezone, e.g. Asia/Shanghai',
        },
      },
      required: ['cron'],
    },
    inputSchema: { type: 'object', properties: {} },
    outputSchema: {
      type: 'object',
      properties: { triggeredAt: { type: 'string' } },
    },
  },
  {
    type: 'webhook_trigger',
    category: 'TRIGGER',
    label: 'Webhook Trigger',
    icon: 'ApiOutlined',
    description: 'Trigger workflow via HTTP webhook (HMAC-signed)',
    configSchema: {
      type: 'object',
      properties: {
        path: {
          type: 'string',
          description:
            'Webhook endpoint path segment, e.g. "order-paid". Final URL: POST /api/workflow/webhook/{path}',
        },
        method: {
          type: 'string',
          enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
          description: 'HTTP method the webhook accepts',
        },
        secret: {
          type: 'string',
          description:
            'HMAC-SHA256 secret. Caller must send X-Workflow-Signature: sha256=HEX(HMAC(secret, "{ts}.{rawBody}")) and X-Workflow-Timestamp.',
        },
      },
      required: ['path', 'method', 'secret'],
    },
    inputSchema: {
      type: 'object',
      properties: {
        body: { type: 'object' },
        headers: { type: 'object' },
        query: { type: 'object' },
      },
    },
    outputSchema: { type: 'object', properties: { body: { type: 'object' } } },
  },
  {
    type: 'event_trigger',
    category: 'TRIGGER',
    label: 'Event Trigger',
    icon: 'ThunderboltOutlined',
    description: 'Trigger workflow on an internal event (Temporal Signal)',
    configSchema: {
      type: 'object',
      properties: {
        eventName: {
          type: 'string',
          description: 'Internal event/signal name to listen for',
        },
        filterExpression: {
          type: 'string',
          description: 'Optional expression to filter events',
        },
      },
      required: ['eventName'],
    },
    inputSchema: {
      type: 'object',
      properties: { payload: { type: 'object' } },
    },
    outputSchema: {
      type: 'object',
      properties: { payload: { type: 'object' } },
    },
  },
  {
    type: 'manual_trigger',
    category: 'TRIGGER',
    label: 'Manual Trigger',
    icon: 'PlayCircleOutlined',
    description: 'Trigger workflow manually for testing or one-time execution',
    configSchema: {
      type: 'object',
      properties: {
        inputSchema: {
          type: 'object',
          description: 'JSON Schema defining expected manual input',
        },
      },
      required: [],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: { type: 'object', properties: { data: { type: 'object' } } },
  },

  // ─── ACTION ────────────────────────────────────────────────────────────────
  {
    type: 'http_request',
    category: 'ACTION',
    label: 'HTTP Request',
    icon: 'GlobalOutlined',
    description: 'Make an HTTP request to an external API',
    configSchema: {
      type: 'object',
      properties: {
        url: { type: 'string', description: 'Request URL' },
        method: {
          type: 'string',
          enum: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'],
          description: 'HTTP method',
        },
        headers: { type: 'object', description: 'Request headers (JSON)' },
        body: { type: 'object', description: 'Request body (JSON)' },
        authentication: {
          type: 'string',
          enum: ['none', 'basic', 'bearer', 'apiKey', 'oauth2'],
          description: 'Authentication type',
        },
        timeout: {
          type: 'number',
          description: 'Request timeout in milliseconds',
        },
        retryOnFail: { type: 'boolean', description: 'Retry on failure' },
        maxRetries: { type: 'number', description: 'Maximum retry attempts' },
        retryInterval: {
          type: 'number',
          description: 'Interval between retries (ms)',
        },
        followRedirects: {
          type: 'boolean',
          description: 'Follow HTTP redirects',
        },
        responseFormat: {
          type: 'string',
          enum: ['json', 'text', 'binary'],
          description: 'Expected response format',
        },
        ignoreSslErrors: {
          type: 'boolean',
          description: 'Ignore SSL certificate errors',
        },
      },
      required: ['url', 'method'],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: {
        status: { type: 'number' },
        data: { type: 'object' },
        headers: { type: 'object' },
      },
    },
  },
  {
    type: 'db_query',
    category: 'ACTION',
    label: 'Database Query',
    icon: 'DatabaseOutlined',
    description: 'Execute a database read query (SELECT)',
    configSchema: {
      type: 'object',
      properties: {
        operation: {
          type: 'string',
          enum: ['query', 'execute'],
          description:
            'query = read (SELECT), execute = write (INSERT/UPDATE/DELETE)',
        },
        query: { type: 'string', description: 'SQL statement' },
        params: {
          type: 'array',
          items: { type: 'string' },
          description: 'Parameterized values ($1, $2...)',
        },
        datasource: {
          type: 'string',
          description: 'Database connection identifier',
        },
        timeout: {
          type: 'number',
          description: 'Query timeout in milliseconds',
        },
      },
      required: ['query'],
    },
    inputSchema: { type: 'object', properties: {} },
    outputSchema: {
      type: 'object',
      properties: { rows: { type: 'array' }, rowCount: { type: 'number' } },
    },
  },
  {
    type: 'db_execute',
    category: 'ACTION',
    label: 'Database Execute',
    icon: 'ConsoleSqlOutlined',
    description: 'Execute a database write operation (INSERT/UPDATE/DELETE)',
    configSchema: {
      type: 'object',
      properties: {
        operation: {
          type: 'string',
          enum: ['insert', 'update', 'delete', 'raw'],
          description: 'Write operation type',
        },
        table: { type: 'string', description: 'Target table name' },
        data: { type: 'object', description: 'Data to insert/update (JSON)' },
        where: {
          type: 'string',
          description: 'WHERE condition for update/delete',
        },
        rawSql: {
          type: 'string',
          description: 'Raw SQL for complex writes (when operation=raw)',
        },
        params: {
          type: 'array',
          items: { type: 'string' },
          description: 'Parameterized values',
        },
        datasource: {
          type: 'string',
          description: 'Database connection identifier',
        },
        timeout: {
          type: 'number',
          description: 'Execution timeout in milliseconds',
        },
      },
      required: ['operation'],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: {
        affectedRows: { type: 'number' },
        insertedId: { type: 'string' },
      },
    },
  },
  {
    type: 'send_notification',
    category: 'ACTION',
    label: 'Send Notification',
    icon: 'BellOutlined',
    description: 'Send a notification via email, Slack, or webhook',
    configSchema: {
      type: 'object',
      properties: {
        channel: {
          type: 'string',
          enum: ['email', 'slack', 'webhook', 'dingtalk', 'wecom'],
          description: 'Notification channel',
        },
        recipients: {
          type: 'array',
          items: { type: 'string' },
          description: 'Recipient list (emails, user IDs, or webhook URLs)',
        },
        subject: {
          type: 'string',
          description: 'Message subject (for email channel)',
        },
        message: {
          type: 'string',
          description:
            'Notification message body (supports template variables)',
        },
        templateId: {
          type: 'string',
          description: 'Message template ID (optional, overrides message)',
        },
      },
      required: ['channel', 'recipients', 'message'],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: { sent: { type: 'boolean' }, messageId: { type: 'string' } },
    },
  },
  {
    type: 'code',
    category: 'ACTION',
    label: 'Code',
    icon: 'CodeOutlined',
    description: 'Execute custom JavaScript code for data transformation',
    configSchema: {
      type: 'object',
      properties: {
        script: { type: 'string', description: 'JavaScript code to execute' },
        mode: {
          type: 'string',
          enum: ['runOnceForAll', 'runOnceForEach'],
          description: 'Execution mode: run once for all items or per item',
        },
        timeout: {
          type: 'number',
          description: 'Script execution timeout (ms)',
        },
      },
      required: ['script'],
    },
    inputSchema: {
      type: 'object',
      properties: { data: { type: 'object' }, items: { type: 'array' } },
    },
    outputSchema: {
      type: 'object',
      properties: { result: { type: 'object' } },
    },
  },

  // ─── DATA PROCESSING ───────────────────────────────────────────────────────
  {
    type: 'set_variable',
    category: 'ACTION',
    label: 'Set Variable',
    icon: 'FormOutlined',
    description: 'Set, transform, or rename variables in the workflow context',
    configSchema: {
      type: 'object',
      properties: {
        assignments: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              name: { type: 'string' },
              value: { type: 'string' },
            },
          },
          description: 'Variable assignments (name → expression)',
        },
        keepOnlySet: {
          type: 'boolean',
          description: 'Remove all other fields, keep only assigned',
        },
      },
      required: ['assignments'],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: { type: 'object', properties: { data: { type: 'object' } } },
  },

  // ─── CONDITION ─────────────────────────────────────────────────────────────
  {
    type: 'if_else',
    category: 'CONDITION',
    label: 'If/Else',
    icon: 'BranchesOutlined',
    description: 'Branch workflow based on a condition',
    configSchema: {
      type: 'object',
      properties: {
        conditions: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              field: { type: 'string' },
              operator: { type: 'string' },
              value: { type: 'string' },
            },
          },
          description: 'Condition rules (field + operator + value)',
        },
        combineOperation: {
          type: 'string',
          enum: ['AND', 'OR'],
          description: 'How to combine multiple conditions',
        },
        fallbackExpression: {
          type: 'string',
          description:
            'Fallback: raw expression (if conditions array is empty)',
        },
      },
      required: [],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: { branch: { type: 'string', enum: ['true', 'false'] } },
    },
  },
  {
    type: 'switch',
    category: 'CONDITION',
    label: 'Switch',
    icon: 'PartitionOutlined',
    description: 'Multi-way branch based on a field value',
    configSchema: {
      type: 'object',
      properties: {
        field: { type: 'string', description: 'Field to evaluate' },
        cases: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              value: { type: 'string' },
              label: { type: 'string' },
            },
          },
          description: 'Case branches (value → output handle)',
        },
        defaultCase: {
          type: 'string',
          description: 'Default branch label when no case matches',
        },
      },
      required: ['field', 'cases'],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: { matchedCase: { type: 'string' } },
    },
  },

  // ─── FLOW CONTROL ──────────────────────────────────────────────────────────
  {
    type: 'for_each',
    category: 'LOOP',
    label: 'For Each',
    icon: 'RetweetOutlined',
    description: 'Iterate over an array field',
    configSchema: {
      type: 'object',
      properties: {
        iteratorField: {
          type: 'string',
          description: 'Path to the array field to iterate',
        },
        concurrency: {
          type: 'number',
          description: 'Parallel concurrency (1 = sequential)',
        },
        batchSize: {
          type: 'number',
          description: 'Process items in batches of this size',
        },
        errorPolicy: {
          type: 'string',
          enum: ['stop', 'continue', 'collect'],
          description:
            'Behavior on item failure: stop all, continue, or collect errors',
        },
      },
      required: ['iteratorField'],
    },
    inputSchema: { type: 'object', properties: { items: { type: 'array' } } },
    outputSchema: {
      type: 'object',
      properties: {
        currentItem: { type: 'object' },
        index: { type: 'number' },
        results: { type: 'array' },
      },
    },
  },
  {
    type: 'delay',
    category: 'FLOW_CONTROL',
    label: 'Delay/Wait',
    icon: 'HourglassOutlined',
    description:
      'Pause workflow execution for a specified duration (Temporal Timer)',
    configSchema: {
      type: 'object',
      properties: {
        delayType: {
          type: 'string',
          enum: ['fixedDuration', 'untilTime', 'untilSignal'],
          description: 'Type of delay',
        },
        duration: {
          type: 'number',
          description: 'Delay duration in seconds (for fixedDuration)',
        },
        untilTime: {
          type: 'string',
          description: 'Resume at ISO datetime (for untilTime)',
        },
        signalName: {
          type: 'string',
          description: 'Signal name to wait for (for untilSignal)',
        },
      },
      required: ['delayType'],
    },
    inputSchema: { type: 'object', properties: {} },
    outputSchema: {
      type: 'object',
      properties: {
        resumedAt: { type: 'string' },
        resumeReason: { type: 'string' },
      },
    },
  },
  {
    type: 'parallel',
    category: 'FLOW_CONTROL',
    label: 'Parallel',
    icon: 'ForkOutlined',
    description:
      'Execute multiple branches in parallel and wait for all to complete',
    configSchema: {
      type: 'object',
      properties: {
        branches: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              label: { type: 'string' },
            },
          },
          description: 'Named parallel branches',
        },
        waitMode: {
          type: 'string',
          enum: ['all', 'any', 'count'],
          description: 'Wait for all, any one, or N branches to complete',
        },
        waitCount: {
          type: 'number',
          description: 'Number of branches to wait for (when waitMode=count)',
        },
      },
      required: ['branches'],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: { results: { type: 'array' } },
    },
  },
  {
    type: 'error_handler',
    category: 'FLOW_CONTROL',
    label: 'Error Handler',
    icon: 'WarningOutlined',
    description: 'Catch errors from upstream nodes and execute fallback logic',
    configSchema: {
      type: 'object',
      properties: {
        errorTypes: {
          type: 'array',
          items: { type: 'string' },
          description: 'Error types to catch (empty = catch all)',
        },
        retryPolicy: {
          type: 'string',
          enum: ['none', 'fixed', 'exponential'],
          description: 'Retry strategy before triggering error handler',
        },
        maxRetries: { type: 'number', description: 'Maximum retry attempts' },
        retryInterval: {
          type: 'number',
          description: 'Initial retry interval in seconds',
        },
        fallbackAction: {
          type: 'string',
          enum: ['continue', 'stop', 'goto'],
          description:
            'Action after catching: continue downstream, stop workflow, or goto a specific node',
        },
        gotoNodeId: {
          type: 'string',
          description: 'Target node ID (when fallbackAction=goto)',
        },
      },
      required: [],
    },
    inputSchema: { type: 'object', properties: { error: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: { error: { type: 'object' }, handled: { type: 'boolean' } },
    },
  },

  // ─── APPROVAL ──────────────────────────────────────────────────────────────
  {
    type: 'approval',
    category: 'APPROVAL',
    label: 'Human Approval',
    icon: 'CheckCircleOutlined',
    description: 'Pause workflow and wait for human approval (Temporal Signal)',
    configSchema: {
      type: 'object',
      properties: {
        approvers: {
          type: 'array',
          items: { type: 'string' },
          description: 'Approver user IDs or emails',
        },
        approvalMode: {
          type: 'string',
          enum: ['any', 'all', 'percentage'],
          description:
            'any = one approver, all = unanimous, percentage = quorum',
        },
        minApprovalCount: {
          type: 'number',
          description: 'Minimum approvals needed (for percentage mode)',
        },
        timeout: { type: 'number', description: 'Approval timeout in seconds' },
        timeoutAction: {
          type: 'string',
          enum: ['auto_approve', 'auto_reject', 'escalate'],
          description: 'Action when approval times out',
        },
        escalateTo: {
          type: 'array',
          items: { type: 'string' },
          description: 'Escalation targets (when timeoutAction=escalate)',
        },
        reminderInterval: {
          type: 'number',
          description: 'Reminder interval in hours (0 = no reminder)',
        },
        allowDelegate: {
          type: 'boolean',
          description: 'Allow approvers to delegate to others',
        },
      },
      required: ['approvers'],
    },
    inputSchema: {
      type: 'object',
      properties: { requestData: { type: 'object' } },
    },
    outputSchema: {
      type: 'object',
      properties: {
        approved: { type: 'boolean' },
        approvedBy: { type: 'string' },
        comment: { type: 'string' },
      },
    },
  },

  // ─── SUB WORKFLOW ──────────────────────────────────────────────────────────
  {
    type: 'sub_workflow',
    category: 'SUB_WORKFLOW',
    label: 'Sub Workflow',
    icon: 'SubnodeOutlined',
    description:
      'Call another workflow as a sub-process (Temporal Child Workflow)',
    configSchema: {
      type: 'object',
      properties: {
        workflowId: {
          type: 'string',
          description: 'Target workflow ID to invoke',
        },
        inputMapping: {
          type: 'object',
          description: 'Map current context fields to child workflow input',
        },
        waitForCompletion: {
          type: 'boolean',
          description: 'Wait for child workflow to finish (sync vs async)',
        },
        timeout: {
          type: 'number',
          description: 'Child workflow timeout in seconds',
        },
      },
      required: ['workflowId'],
    },
    inputSchema: { type: 'object', properties: { data: { type: 'object' } } },
    outputSchema: {
      type: 'object',
      properties: { result: { type: 'object' }, status: { type: 'string' } },
    },
  },
];

export async function seedNodeTypes(prisma: PrismaClient) {
  console.log('Seeding workflow node types...');
  for (const nodeType of NODE_TYPES) {
    await prisma.workflowNodeType.upsert({
      where: { type: nodeType.type },
      update: {
        category: nodeType.category as any,
        label: nodeType.label,
        icon: nodeType.icon,
        description: nodeType.description,
        configSchema: nodeType.configSchema,
        inputSchema: nodeType.inputSchema,
        outputSchema: nodeType.outputSchema,
      },
      create: {
        type: nodeType.type,
        category: nodeType.category as any,
        label: nodeType.label,
        icon: nodeType.icon,
        description: nodeType.description,
        configSchema: nodeType.configSchema,
        inputSchema: nodeType.inputSchema,
        outputSchema: nodeType.outputSchema,
      },
    });
  }
  console.log(`Seeded ${NODE_TYPES.length} node types.`);
}
