/**
 * Extract Facebook Reaction list data from GraphQL JSON responses.
 */

import type { FbReactionData } from "../../../types.js";
import { dig, asStr, edgeNodes } from "./helpers.js";

export function extractReactions(
  body: Record<string, unknown>,
): FbReactionData[] {
  try {
    // Known paths for reactor lists
    const reactorNodes =
      findReactorNodes(body, "data", "node", "feedback", "reactors") ??
      findReactorNodes(body, "data", "node", "reactors") ??
      findReactorNodes(body, "data", "feedback", "reactors") ??
      findReactorNodes(body, "node", "feedback", "reactors");

    if (!reactorNodes || reactorNodes.length === 0) return [];

    // Determine post_id from context
    const postId =
      asStr(dig(body, "data", "node", "id") as Record<string, unknown> | undefined) ??
      asStr(dig(body, "data", "node", "feedback", "id") as Record<string, unknown> | undefined) ??
      "";

    const reactions: FbReactionData[] = [];
    for (const node of reactorNodes) {
      const reaction = nodeToReaction(node, postId);
      if (reaction) reactions.push(reaction);
    }
    return reactions;
  } catch (err) {
    console.warn("[extractReactions] Unexpected error:", (err as Error).message);
    return [];
  }
}

function findReactorNodes(
  body: Record<string, unknown>,
  ...path: string[]
): Array<Record<string, unknown>> | null {
  const connection = dig(body, ...path);
  if (!connection) return null;
  const nodes = edgeNodes<Record<string, unknown>>(connection);
  return nodes.length > 0 ? nodes : null;
}

const VALID_REACTIONS = new Set([
  "like", "love", "haha", "wow", "sad", "angry", "care",
]);

function nodeToReaction(
  node: Record<string, unknown>,
  postId: string,
): FbReactionData | null {
  const userId = asStr(node, "id");
  const userName = asStr(node, "name") ?? "";

  if (!userId) {
    console.warn("[extractReactions] Skipping reactor without id");
    return null;
  }

  const rawType =
    asStr(node, "reaction_type") ??
    asStr(dig(node, "i18n_reaction_type") as Record<string, unknown> | undefined) ??
    asStr(dig(node, "reaction") as Record<string, unknown> | undefined, "type") ??
    "like";

  const normalized = rawType.toLowerCase().replace(/^reaction_/i, "");
  const reactionType = VALID_REACTIONS.has(normalized)
    ? (normalized as FbReactionData["reaction_type"])
    : "like";

  return {
    post_id: postId,
    user_id: userId,
    user_name: userName,
    user_url:
      asStr(node, "url") ??
      asStr(node, "uri") ??
      asStr(dig(node, "profile_url") as Record<string, unknown> | undefined),
    reaction_type: reactionType,
  };
}
