import { createLightNode, waitForRemotePeer, Protocols, createEncoder } from '@waku/sdk';
import protobuf from 'protobufjs';
import { Task } from "../../../prisma/generated/client";

// Define the Waku Content Topic for our Agent Network
export const VIBEWORK_WAKU_TOPIC = '/vibework/1/a2a-events/proto';

// Define the Protobuf Message Structure
const EventMessage = new protobuf.Type('EventMessage')
  .add(new protobuf.Field('taskId', 1, 'string'))
  .add(new protobuf.Field('eventType', 2, 'string'))
  .add(new protobuf.Field('payloadJson', 3, 'string'))
  .add(new protobuf.Field('timestamp', 4, 'uint64'));

// Singleton Waku Node Promise
let nodePromise: Promise<Awaited<ReturnType<typeof createLightNode>>> | null = null;

async function getWakuNode() {
  if (nodePromise) return nodePromise;

  console.log('[Waku] Initializing Waku Light Node...');
  nodePromise = createLightNode({ defaultBootstrap: true })
    .then(async (node) => {
      await node.start();
      console.log('[Waku] Node started, waiting for remote peers...');
      await waitForRemotePeer(node, [Protocols.LightPush], 10000); // 10s timeout
      console.log('[Waku] Connected to remote peers!');
      return node;
    })
    .catch((err) => {
      console.error('[Waku] Failed to initialize node:', err);
      nodePromise = null;
      throw err;
    });

  return nodePromise;
}

/**
 * 2026 Standard: True Waku GossipSub Broadcaster
 * Broadcasts an A2A Event to the decentralized Waku Network.
 */
export async function broadcastViaWaku(task: Task) {
  try {
    // Start node initialization in the background if not started
    getWakuNode().catch(() => {});
    
    // We do not await node connection here to prevent blocking the API route.
    // Instead we do a fire-and-forget or fast timeout push.
    // To ensure fast API response, we will just use the node if it's ready.
    if (!nodePromise) return;

    const node = await getWakuNode();
    
    const payload = {
      task_id: task.id,
      title: task.title,
      reward_amount: task.reward_amount,
      reward_currency: task.reward_currency,
      required_stack: task.required_stack,
      expires_at: task.expires_at,
    };

    const payloadJson = JSON.stringify(payload);
    
    const message = EventMessage.create({
      taskId: task.id,
      eventType: "NEW_BOUNTY",
      payloadJson,
      timestamp: Date.now(),
    });

    const serializedMessage = EventMessage.encode(message).finish();
    const encoder = createEncoder({ contentTopic: VIBEWORK_WAKU_TOPIC } as Parameters<typeof createEncoder>[0]);

    console.log(`[Waku Broadcaster] Pushing intent ${task.id} to P2P network...`);
    const pushResponse = await node.lightPush.send(encoder, { payload: serializedMessage });

    if (pushResponse.failures && pushResponse.failures.length > 0) {
      console.error('[Waku Error] Failed to push message to Waku:', pushResponse.failures);
      return { status: "error", error: pushResponse.failures };
    } else {
      console.log(`[Waku Broadcaster] Success! Gossip propagated to peers.`);
      return { status: "success", topic: VIBEWORK_WAKU_TOPIC };
    }
  } catch (error: unknown) {
    const message = error instanceof Error ? error.message : String(error);
    console.error('[Waku System Error] Failed to broadcast to Waku:', message);
    return { status: "error", error: message };
  }
}
