import type { TopologyNode, TopologyEdge } from '../../types/index';
import { EDGE_LABEL, NODE_TYPE, INFRA_NODE_ID } from './constants';

/**
 * Infers logical edges based on known node types and common architectural patterns.
 *
 * @param nodes List of identified topology nodes.
 * @returns An array of generated topology edges.
 */
export function inferNodeEdges(nodes: TopologyNode[]): TopologyEdge[] {
  const edges: TopologyEdge[] = [];
  const busNode = nodes.find(
    (node) =>
      node.type === NODE_TYPE.BUS ||
      node.id === INFRA_NODE_ID.AGENT_BUS ||
      node.id === INFRA_NODE_ID.BUS ||
      node.label.toLowerCase().includes('bus')
  );
  const busId = busNode?.id ?? INFRA_NODE_ID.AGENT_BUS;

  // E. Real-time Signaling Flow Components (Moved up for availability)
  const hasRealtimeBridge = nodes.some((node) => node.id === INFRA_NODE_ID.REALTIME_BRIDGE);
  const hasRealtimeBus = nodes.some((node) => node.id === INFRA_NODE_ID.REALTIME_BUS);

  // A. Agent <-> Bus Relationship
  nodes
    .filter(
      (node) => node.type === NODE_TYPE.AGENT || node.id === 'monitor' || node.id === 'superclaw'
    )
    .forEach((agent) => {
      edges.push({
        id: `${agent.id}-${busId}-orch`,
        source: agent.id,
        target: busId,
        label: EDGE_LABEL.ORCHESTRATE,
      });
      edges.push({
        id: `${busId}-${agent.id}-signal`,
        source: busId,
        target: agent.id,
        label: EDGE_LABEL.SIGNAL,
      });

      // Hot Path (SC-P3): Agents emit real-time chunks directly to IoT Core for sub-50ms latency
      if (hasRealtimeBus) {
        edges.push({
          id: `${agent.id}-realtime-hotpath`,
          source: agent.id,
          target: INFRA_NODE_ID.REALTIME_BUS,
          label: EDGE_LABEL.REALTIME,
        });
      }
    });

  // B. Scheduler to Heartbeat
  edges.push({
    id: 'base-scheduler-heartbeat',
    source: INFRA_NODE_ID.SCHEDULER,
    target: INFRA_NODE_ID.HEARTBEAT,
    label: EDGE_LABEL.HEARTBEAT,
  });
  edges.push({
    id: `heartbeat-${busId}`,
    source: INFRA_NODE_ID.HEARTBEAT,
    target: busId,
    label: EDGE_LABEL.SIGNAL,
  });

  // C. API/Webhook to Bus
  const apiNode = nodes.find(
    (node) => node.id === INFRA_NODE_ID.WEBHOOK_API || node.id.includes(INFRA_NODE_ID.API)
  );
  if (apiNode) {
    edges.push({
      id: `${apiNode.id}-${busId}`,
      source: apiNode.id,
      target: busId,
      label: EDGE_LABEL.SIGNAL,
    });

    // D. Telegram to API
    edges.push({
      id: 'telegram-api-link',
      source: INFRA_NODE_ID.TELEGRAM,
      target: apiNode.id,
      label: EDGE_LABEL.WEBHOOK,
    });
  }

  // E. Real-time Signaling Flow (Bridge Fallback)
  if (hasRealtimeBridge && busNode) {
    edges.push({
      id: `${busId}-realtime-bridge`,
      source: busId,
      target: INFRA_NODE_ID.REALTIME_BRIDGE,
      label: EDGE_LABEL.SIGNAL,
    });
  }

  if (hasRealtimeBridge && hasRealtimeBus) {
    edges.push({
      id: 'realtime-bridge-to-bus',
      source: INFRA_NODE_ID.REALTIME_BRIDGE,
      target: INFRA_NODE_ID.REALTIME_BUS,
      label: EDGE_LABEL.REALTIME,
    });
  }

  const dashboardNode = nodes.find((node) => node.type === NODE_TYPE.DASHBOARD);
  if (dashboardNode) {
    if (hasRealtimeBus) {
      edges.push({
        id: `realtime-bus-to-dash`,
        source: INFRA_NODE_ID.REALTIME_BUS,
        target: dashboardNode.id,
        label: EDGE_LABEL.REALTIME,
      });
    }

    // F. Dashboard explicitly linked to SuperClaw
    const mainAgent = nodes.find((node) => node.id === 'superclaw');
    if (mainAgent) {
      edges.push({
        id: `dashboard-superclaw-link`,
        source: dashboardNode.id,
        target: mainAgent.id,
        label: EDGE_LABEL.ORCHESTRATE,
      });
    }

    // G. Dashboard Outgoing to API and Infra
    if (apiNode) {
      edges.push({
        id: `dashboard-api-link`,
        source: dashboardNode.id,
        target: apiNode.id,
        label: EDGE_LABEL.INBOUND,
      });
    }

    const coreTables = [INFRA_NODE_ID.CLAWDB];

    coreTables.forEach((table) => {
      if (nodes.some((node) => node.id === table)) {
        edges.push({
          id: `dashboard-query-${table}`,
          source: dashboardNode.id,
          target: table,
          label: EDGE_LABEL.QUERY,
        });
      }
    });

    const coreBuckets = [INFRA_NODE_ID.STAGING_BUCKET, INFRA_NODE_ID.KNOWLEDGE_BUCKET];

    coreBuckets.forEach((bucket) => {
      if (nodes.some((node) => node.id === bucket)) {
        edges.push({
          id: `dashboard-manage-${bucket}`,
          source: dashboardNode.id,
          target: bucket,
          label: EDGE_LABEL.MANAGE_FILES,
        });
      }
    });

    // H. Deployer (CodeBuild) Links
    const deployerNode = nodes.find(
      (node) => node.id === INFRA_NODE_ID.DEPLOYER || node.id === 'codebuild'
    );
    if (deployerNode) {
      if (nodes.some((node) => node.id === INFRA_NODE_ID.STAGING_BUCKET)) {
        edges.push({
          id: `${deployerNode.id}-staging-link`,
          source: deployerNode.id,
          target: INFRA_NODE_ID.STAGING_BUCKET,
          label: EDGE_LABEL.DEPLOY,
        });
      }
      if (busNode) {
        edges.push({
          id: `${deployerNode.id}-bus-signal`,
          source: deployerNode.id,
          target: busId,
          label: EDGE_LABEL.SIGNAL,
        });
      }
    }

    // I. SQS to EventBridge
    const sqsNode = nodes.find(
      (node) => node.id === INFRA_NODE_ID.SQS || node.label.includes('SQS')
    );
    if (sqsNode && busNode) {
      edges.push({
        id: `sqs-bus-link`,
        source: sqsNode.id,
        target: busId,
        label: EDGE_LABEL.SIGNAL,
      });
    }

    // J. External / Orphan Connectivity
    const githubNode = nodes.find((n) => n.id === 'github');
    const coderNode = nodes.find((n) => n.id === 'coder' || n.id === 'coderagent');
    if (githubNode && coderNode) {
      edges.push({
        id: 'github-coder-read',
        source: githubNode.id,
        target: coderNode.id,
        label: EDGE_LABEL.READ_FILES,
      });
      edges.push({
        id: 'coder-github-commit',
        source: coderNode.id,
        target: githubNode.id,
        label: EDGE_LABEL.DEPLOY,
      });
    }

    if (githubNode && deployerNode) {
      edges.push({
        id: 'github-deployer-source',
        source: githubNode.id,
        target: deployerNode.id,
        label: EDGE_LABEL.DEPLOY,
      });
    }

    const usersNode = nodes.find((n) => n.id === 'external_users');
    if (usersNode) {
      if (apiNode) {
        edges.push({
          id: 'users-api-request',
          source: usersNode.id,
          target: apiNode.id,
          label: EDGE_LABEL.INBOUND,
        });
      }
      edges.push({
        id: 'users-dash-visit',
        source: usersNode.id,
        target: dashboardNode.id,
        label: EDGE_LABEL.INBOUND,
      });
    }

    // K. Notifier to Telegram (Outbound)
    const notifierNode = nodes.find((n) => n.id === 'notifier' || n.id === INFRA_NODE_ID.NOTIFIER);
    const telegramNode = nodes.find((n) => n.id === INFRA_NODE_ID.TELEGRAM);
    if (notifierNode && telegramNode) {
      edges.push({
        id: 'notifier-telegram-send',
        source: notifierNode.id,
        target: telegramNode.id,
        label: EDGE_LABEL.OUTBOUND,
      });
    }
  }

  return edges;
}
