/**
 * Extract Facebook Page metadata from GraphQL JSON responses.
 */

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

export function extractPageData(
  body: Record<string, unknown>,
): Partial<FbPageData> | null {
  try {
    const page =
      dig(body, "data", "page") ??
      dig(body, "data", "node") ??
      dig(body, "node") ??
      dig(body, "data");

    if (!page || typeof page !== "object") {
      console.warn("[extractPageData] No page node found in response");
      return null;
    }

    const p = page as Record<string, unknown>;
    const pageId = asStr(p, "id") ?? asStr(p, "page_id");
    if (!pageId) {
      console.warn("[extractPageData] Missing page_id");
      return null;
    }

    const name = asStr(p, "name") ?? asStr(p, "display_name") ?? "";

    const result: Partial<FbPageData> = {
      page_id: pageId,
      name,
      category: asStr(p, "category_name") ?? asStr(p, "category"),
      sub_category:
        asStr(dig(p, "category_info", "name") as Record<string, unknown> | undefined) ??
        undefined,
      about: asStr(p, "about") ?? asStr(dig(p, "about_data", "text") as Record<string, unknown> | undefined),
      description: asStr(p, "description") ?? asStr(p, "bio"),
      follower_count: asNum(p, "follower_count") ?? asNum(dig(p, "followers") as Record<string, unknown> | undefined, "count"),
      like_count: asNum(p, "like_count") ?? asNum(dig(p, "page_likers") as Record<string, unknown> | undefined, "count"),
      checkin_count: asNum(p, "checkin_count"),
      verified: asBool(p, "is_verified") ?? asBool(p, "verified"),
      website: asStr(p, "website") ?? asStr(p, "single_line_address"),
      phone: asStr(p, "phone"),
      email: asStr(p, "email") ?? asStr(p, "emails")?.[0],
      address: extractAddress(p),
      profile_photo_url:
        asStr(dig(p, "profile_picture", "uri") as Record<string, unknown> | undefined) ??
        asStr(dig(p, "profilePicLarge", "uri") as Record<string, unknown> | undefined),
      cover_photo_url:
        asStr(dig(p, "cover_photo", "photo", "image", "uri") as Record<string, unknown> | undefined) ??
        asStr(dig(p, "coverPhoto", "photo", "image", "uri") as Record<string, unknown> | undefined),
      creation_date: asStr(p, "creation_date") ?? asStr(p, "created_time"),
      raw: asObj(p),
    };

    // Inline transparency if present
    const transparency = extractInlineTransparency(p);
    if (transparency) {
      result.transparency = transparency;
    }

    return result;
  } catch (err) {
    console.warn("[extractPageData] Unexpected error:", (err as Error).message);
    return null;
  }
}

function extractAddress(p: Record<string, unknown>): string | undefined {
  const loc =
    (dig(p, "location") as Record<string, unknown> | undefined) ??
    (dig(p, "address") as Record<string, unknown> | undefined);
  if (!loc || typeof loc !== "object") return asStr(p, "single_line_address");
  const parts = [
    asStr(loc, "street"),
    asStr(loc, "city"),
    asStr(loc, "state"),
    asStr(loc, "zip"),
    asStr(loc, "country"),
  ].filter(Boolean);
  return parts.length > 0 ? parts.join(", ") : undefined;
}

function extractInlineTransparency(
  p: Record<string, unknown>,
): Partial<FbTransparencyData> | undefined {
  const ti =
    (dig(p, "transparency_info") as Record<string, unknown> | undefined) ??
    (dig(p, "page_transparency") as Record<string, unknown> | undefined);
  if (!ti || typeof ti !== "object") return undefined;

  return {
    manager_countries: extractStringArray(dig(ti, "admin_countries") ?? dig(ti, "manager_countries")),
    name_history: extractNameHistory(dig(ti, "name_changes") ?? dig(ti, "history")),
    created_date: asStr(ti, "creation_date"),
    runs_political_ads: asBool(ti, "has_political_ads") ?? asBool(ti, "runs_political_ads"),
    raw: asObj(ti),
  };
}

function extractStringArray(val: unknown): string[] | undefined {
  if (!Array.isArray(val)) return undefined;
  return val
    .map((v) => (typeof v === "string" ? v : typeof v === "object" && v ? (v as Record<string, unknown>).name ?? (v as Record<string, unknown>).country : undefined))
    .filter((v): v is string => typeof v === "string");
}

function extractNameHistory(
  val: unknown,
): Array<{ name: string; changed_at?: string }> | undefined {
  if (!Array.isArray(val)) return undefined;
  const mapped = val
    .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");
      if (!name) return null;
      const changedAt = asStr(e, "changed_at") ?? asStr(e, "timestamp");
      return { name, ...(changedAt ? { changed_at: changedAt } : {}) };
    });
  return mapped.filter((v): v is { name: string; changed_at?: string } => v !== null);
}
