/**
 * Facebook Graph API 工具
 *
 * 在 OAuth callback 之后、auth state machine 的 `syncingFacebookBackend` actor
 * 成功换取业务 token 之后调用 —— 用 accessToken 调 `/me` 拉用户资料（id / name
 * / email / picture），把 pictureUrl 写入 `UserStorage.setAvatarUrl()`、
 * id 写入 `AuthStorage.setFacebookId()`。
 *
 * 端点：`https://graph.facebook.com/me?fields=id,name,email,picture.type(large)&access_token=...`
 *   - `picture.type(large)` 返回 ~200px 头像 URL（默认 square 50px 太小）
 *   - 不指定 version 走最新稳定版
 *   - 不需要 appId / appSecret（accessToken 自身就是凭证）
 */
import { FacebookUserData } from "@/data/dto/auth";
import { Logger, Result, toError } from "@/utils";

const log = new Logger("FacebookGraph");

/** Facebook Graph `/me` 端点。 */
const GRAPH_ME_URL = "https://graph.facebook.com/me";

/**
 * 拉取字段集合：
 *   - id / name / email —— 给本地 FacebookUserData DTO
 *   - picture.type(large) —— 头像 URL（默认 square 50px 太小）
 */
const FIELDS = "id,name,email,picture.type(large)";

/**
 * 用 accessToken 调 Facebook Graph `/me` 拉用户资料。
 *
 * 错误处理：返回 `Result<FacebookUserData>` 而非 throw —— 调用方在
 * auth state machine actor 内可走「best-effort」路径，失败只 warn 不
 * 让 Facebook 登录整条流挂掉（后端业务 token 已经换到，头像只是锦上添花）。
 */
export async function fetchFacebookUserData(
  accessToken: string,
): Promise<Result<FacebookUserData>> {
  if (!accessToken) {
    return Result.err(new Error("fetchFacebookUserData: accessToken is empty"));
  }

  const url = `${GRAPH_ME_URL}?fields=${encodeURIComponent(FIELDS)}&access_token=${encodeURIComponent(accessToken)}`;

  log.debug({ url: url.replace(accessToken, "<redacted>") }, "fetchFacebookUserData REQUEST");

  try {
    const res = await fetch(url, { method: "GET" });
    const json = (await res.json()) as Record<string, unknown>;

    if (!res.ok) {
      const errBody = (json?.error as Record<string, unknown> | undefined) ?? {};
      const message =
        typeof errBody.message === "string"
          ? errBody.message
          : `Graph /me failed: HTTP ${res.status}`;
      log.warn({ status: res.status, body: errBody }, "fetchFacebookUserData FAILED");
      return Result.err(new Error(message));
    }

    // 提取 picture.data.url —— Graph API 返回嵌套结构
    const pictureUrl = extractPictureUrl(json.picture);

    const data = FacebookUserData.from({
      id: typeof json.id === "string" ? json.id : null,
      name: typeof json.name === "string" ? json.name : null,
      email: typeof json.email === "string" ? json.email : null,
      pictureUrl,
    });

    log.debug(
      {
        hasId: !!data.id,
        hasName: !!data.name,
        hasEmail: !!data.email,
        hasPicture: !!data.pictureUrl,
      },
      "fetchFacebookUserData SUCCESS",
    );
    return Result.ok(data);
  } catch (e) {
    const err = toError(e);
    log.error({ err }, "fetchFacebookUserData THREW");
    return Result.err(err);
  }
}

/**
 * 安全提取 `picture.data.url` —— 容错处理：
 *   - 缺字段 / 类型不对 → null（头像可选）
 *   - Graph API 偶尔返回 `picture: false`（没设头像）→ null
 */
function extractPictureUrl(raw: unknown): string | null {
  if (!raw || typeof raw !== "object") return null;
  const data = (raw as { data?: unknown }).data;
  if (!data || typeof data !== "object") return null;
  const url = (data as { url?: unknown }).url;
  return typeof url === "string" && url.length > 0 ? url : null;
}
