import { getMetaConfig, getMetaGraphBase, getMetaRedirectUri } from "@/lib/env";
import { metaGraphGetUrl, withMetaAccessTokenBody } from "@/lib/social/meta-graph";
import { metaScopesErrorMessage } from "@/lib/social/meta-scopes";
function graphUrl(path: string): string {
  const base = getMetaGraphBase();
  return path.startsWith("http") ? path : `${base}${path.startsWith("/") ? path : `/${path}`}`;
}

export function getMetaOAuthScopes(platform: "facebook" | "instagram"): string[] {
  const config = getMetaConfig();
  return platform === "instagram" ? config.instagramScopes : config.facebookScopes;
}

export function buildMetaAuthUrl(state: string, platform: "facebook" | "instagram"): string {
  const config = getMetaConfig();
  if (!config.appId || !config.redirectUri) {
    throw new Error("Meta (Facebook) OAuth is not configured");
  }

  const scopes = getMetaOAuthScopes(platform);
  const validation =
    platform === "instagram"
      ? config.instagramScopeValidation
      : config.facebookScopeValidation;
  const scopeError = metaScopesErrorMessage(validation);
  if (scopeError) {
    console.warn(`[meta-oauth] ${scopeError}`);
  }

  const params = new URLSearchParams({
    client_id: config.appId,
    redirect_uri: getMetaRedirectUri(platform),
    state,
    scope: scopes.join(","),
    response_type: "code",
  });

  const version = config.graphVersion;
  return `https://www.facebook.com/${version}/dialog/oauth?${params.toString()}`;
}

export async function exchangeMetaCode(
  code: string,
  redirectUri?: string,
): Promise<{
  accessToken: string;
  expiresIn?: number;
}> {
  const { appId, appSecret } = getMetaConfig();
  const uri = redirectUri ?? getMetaRedirectUri("facebook");
  const params = new URLSearchParams({
    client_id: appId,
    client_secret: appSecret,
    redirect_uri: uri,
    code,
  });

  const res = await fetch(graphUrl(`/oauth/access_token?${params.toString()}`));
  const data = (await res.json()) as {
    access_token?: string;
    expires_in?: number;
    error?: { message?: string };
  };

  if (!res.ok || !data.access_token) {
    throw new Error(data.error?.message ?? "Meta token exchange failed");
  }

  const longLived = await exchangeLongLivedToken(data.access_token);
  return longLived;
}

async function exchangeLongLivedToken(shortToken: string) {
  const { appId, appSecret } = getMetaConfig();
  const params = new URLSearchParams({
    grant_type: "fb_exchange_token",
    client_id: appId,
    client_secret: appSecret,
    fb_exchange_token: shortToken,
  });
  const res = await fetch(graphUrl(`/oauth/access_token?${params.toString()}`));
  const data = (await res.json()) as { access_token?: string; expires_in?: number };
  if (!data.access_token) return { accessToken: shortToken };
  return { accessToken: data.access_token, expiresIn: data.expires_in };
}

/** Re-exchange a user token for a fresh long-lived token (Meta "refresh"). */
export async function refreshMetaUserToken(userToken: string): Promise<{
  accessToken: string;
  expiresIn?: number;
}> {
  return exchangeLongLivedToken(userToken);
}

export interface MetaPageInfo {
  pageId: string;
  pageName: string;
  pageAccessToken: string;
  igUserId?: string;
}

export async function fetchMetaPages(userToken: string): Promise<MetaPageInfo[]> {
  const res = await fetch(
    metaGraphGetUrl("/me/accounts", userToken, {
      fields: "id,name,access_token,instagram_business_account",
    }),
  );
  const data = (await res.json()) as {
    data?: Array<{
      id: string;
      name: string;
      access_token: string;
      instagram_business_account?: { id: string };
    }>;
    error?: { message?: string };
  };

  if (!res.ok || !data.data?.length) {
    const hint =
      data.error?.message ??
      "No Facebook Pages found. Ensure your Meta app has the Page use case and pages_show_list permission.";
    throw new Error(hint);
  }

  return data.data.map((p) => ({
    pageId: p.id,
    pageName: p.name,
    pageAccessToken: p.access_token,
    igUserId: p.instagram_business_account?.id,
  }));
}

export async function resolveMetaConnection(
  userToken: string,
  platform: "facebook" | "instagram",
  options?: { preferPageId?: string },
): Promise<{
  profileName: string;
  externalId: string;
  publishToken: string;
  accessToken: string;
  expiresAt?: string;
}> {
  const pages = await fetchMetaPages(userToken);

  if (platform === "facebook") {
    const page =
      (options?.preferPageId
        ? pages.find((p) => p.pageId === options.preferPageId)
        : undefined) ?? pages[0];
    return {
      profileName: page.pageName,
      externalId: page.pageId,
      publishToken: page.pageAccessToken,
      accessToken: userToken,
    };
  }

  const withInstagram = pages.filter((p) => p.igUserId);
  const page =
    (options?.preferPageId
      ? withInstagram.find((p) => p.pageId === options.preferPageId)
      : undefined) ??
    withInstagram[0] ??
    pages.find((p) => p.pageId === options?.preferPageId);

  if (!page?.igUserId) {
    const pageList = pages.map((p) => `"${p.pageName}"`).join(", ");
    throw new Error(
      `No Instagram Business account is linked to your Facebook Page(s): ${pageList}. ` +
        "Instagram publishing uses Meta — you log in with Facebook, not a separate Instagram password. " +
        "Fix: Meta Business Suite → Settings → Linked accounts → link Instagram Business/Creator to your Page, then Connect again.",
    );
  }

  const igRes = await fetch(
    metaGraphGetUrl(`/${page.igUserId}`, page.pageAccessToken, {
      fields: "username,name",
    }),
  );
  const ig = (await igRes.json()) as { username?: string; name?: string; error?: { message?: string } };
  if (!igRes.ok) throw new Error(ig.error?.message ?? "Could not load Instagram account");

  return {
    profileName: ig.username ? `@${ig.username}` : (ig.name ?? "Instagram"),
    externalId: page.igUserId,
    publishToken: page.pageAccessToken,
    accessToken: userToken,
  };
}

export function publicImageUrl(imageUrl: string | null | undefined, appOrigin: string): string | null {
  if (!imageUrl) return null;
  const clean = imageUrl.split("#")[0]?.split("?")[0] ?? imageUrl;
  if (clean.startsWith("http")) return clean;
  return `${appOrigin.replace(/\/$/, "")}${clean}`;
}
