/**
 * Extract Facebook Page Transparency data from GraphQL JSON responses.
 */

import type { FbTransparencyData } from "../../../types.js";
import { dig, asStr, asBool, asObj, edgeNodes, epochToIso } from "./helpers.js";

export function extractTransparency(
  body: Record<string, unknown>,
): Partial<FbTransparencyData> | null {
  try {
    const ti =
      (dig(body, "data", "page", "transparency_info") as Record<string, unknown> | undefined) ??
      (dig(body, "data", "node", "transparency_info") as Record<string, unknown> | undefined) ??
      (dig(body, "data", "page", "page_transparency") as Record<string, unknown> | undefined) ??
      (dig(body, "data", "node", "page_transparency_info") as Record<string, unknown> | undefined);

    if (!ti || typeof ti !== "object") {
      console.warn("[extractTransparency] No transparency info found");
      return null;
    }

    return {
      manager_countries: extractManagerCountries(ti),
      name_history: extractNameHistory(ti),
      created_date: extractCreatedDate(ti),
      runs_political_ads:
        asBool(ti, "has_political_ads") ??
        asBool(ti, "runs_political_ads") ??
        asBool(ti, "is_political_advertiser"),
      linked_instagram: extractLinkedInstagram(ti),
      merge_history: extractMergeHistory(ti),
      raw: asObj(ti),
    };
  } catch (err) {
    console.warn("[extractTransparency] Unexpected error:", (err as Error).message);
    return null;
  }
}

function extractManagerCountries(ti: Record<string, unknown>): string[] | undefined {
  // Multiple possible paths
  const countries =
    dig(ti, "admin_countries") ??
    dig(ti, "page_manager_country") ??
    dig(ti, "admins_in_countries");

  if (Array.isArray(countries)) {
    return countries
      .map((c) => {
        if (typeof c === "string") return c;
        if (typeof c === "object" && c) {
          const obj = c as Record<string, unknown>;
          return asStr(obj, "country") ?? asStr(obj, "name") ?? asStr(obj, "code");
        }
        return undefined;
      })
      .filter((c): c is string => !!c);
  }

  // Edges pattern
  const nodes = edgeNodes<Record<string, unknown>>(countries);
  if (nodes.length > 0) {
    return nodes
      .map((n) => asStr(n, "country") ?? asStr(n, "name"))
      .filter((c): c is string => !!c);
  }

  return undefined;
}

function extractNameHistory(
  ti: Record<string, unknown>,
): Array<{ name: string; changed_at?: string }> | undefined {
  const history =
    dig(ti, "name_changes") ??
    dig(ti, "history") ??
    dig(ti, "former_names");

  if (!Array.isArray(history)) return undefined;

  const mapped = history
    .map((entry): { name: string; changed_at?: string } | null => {
      if (typeof entry !== "object" || !entry) return null;
      const e = entry as Record<string, unknown>;
      const name =
        asStr(e, "name") ??
        asStr(e, "previous_name") ??
        asStr(e, "former_name");
      if (!name) return null;

      const changedAt =
        epochToIso(e.changed_at) ??
        epochToIso(e.timestamp) ??
        asStr(e, "date");

      return { name, ...(changedAt ? { changed_at: changedAt } : {}) };
    });
  return mapped.filter((v): v is { name: string; changed_at?: string } => v !== null);
}

function extractCreatedDate(ti: Record<string, unknown>): string | undefined {
  return (
    asStr(ti, "creation_date") ??
    asStr(ti, "created_date") ??
    epochToIso(dig(ti, "creation_time"))
  );
}

function extractLinkedInstagram(ti: Record<string, unknown>): string[] | undefined {
  const ig =
    dig(ti, "linked_instagram") ??
    dig(ti, "connected_instagram_accounts");

  if (Array.isArray(ig)) {
    return ig
      .map((a) => {
        if (typeof a === "string") return a;
        if (typeof a === "object" && a) {
          const obj = a as Record<string, unknown>;
          return asStr(obj, "username") ?? asStr(obj, "name") ?? asStr(obj, "id");
        }
        return undefined;
      })
      .filter((v): v is string => !!v);
  }

  return undefined;
}

function extractMergeHistory(ti: Record<string, unknown>): string[] | undefined {
  const merges =
    dig(ti, "merge_history") ??
    dig(ti, "merged_pages");

  if (Array.isArray(merges)) {
    return merges
      .map((m) => {
        if (typeof m === "string") return m;
        if (typeof m === "object" && m) {
          const obj = m as Record<string, unknown>;
          return asStr(obj, "name") ?? asStr(obj, "id");
        }
        return undefined;
      })
      .filter((v): v is string => !!v);
  }

  return undefined;
}
