import { THREADS_MAX_CHARS } from "@/lib/utils";
import { threadsGraphGet, threadsGraphPost, ThreadsApiError } from "./client";
import type { ThreadsApiCredentials, ThreadsPublishInput, ThreadsPublishResult } from "./types";

const POLL_INTERVAL_MS = 3000;
const POLL_MAX_ATTEMPTS = 20;

export async function publishViaThreadsApi(
  credentials: ThreadsApiCredentials,
  input: ThreadsPublishInput
): Promise<ThreadsPublishResult> {
  if (input.text.length > THREADS_MAX_CHARS) {
    return { success: false, error: `貼文超過 ${THREADS_MAX_CHARS} 字上限`, method: "api" };
  }

  try {
    const containerParams: Record<string, string> = {
      access_token: credentials.accessToken,
      text: input.text,
    };

    if (input.imageUrl) {
      containerParams.media_type = "IMAGE";
      containerParams.image_url = input.imageUrl;
    } else {
      containerParams.media_type = "TEXT";
    }

    if (input.replyToId) {
      containerParams.reply_to_id = input.replyToId;
    }

    const container = await threadsGraphPost<{ id: string }>(
      `/${credentials.userId}/threads`,
      containerParams
    );

    if (!container.id) {
      return { success: false, error: "無法建立發布容器", method: "api" };
    }

    await waitForContainerReady(container.id, credentials.accessToken);

    const published = await threadsGraphPost<{ id: string }>(
      `/${credentials.userId}/threads_publish`,
      {
        access_token: credentials.accessToken,
        creation_id: container.id,
      }
    );

    if (!published.id) {
      return { success: false, error: "發布請求未回傳貼文 ID", method: "api" };
    }

    const permalink = await fetchPermalink(published.id, credentials.accessToken);

    return {
      success: true,
      mediaId: published.id,
      permalink: permalink ?? undefined,
      method: "api",
    };
  } catch (error) {
    const message =
      error instanceof ThreadsApiError
        ? error.message
        : error instanceof Error
          ? error.message
          : "Threads API 發布失敗";
    return { success: false, error: message, method: "api" };
  }
}

async function waitForContainerReady(containerId: string, accessToken: string) {
  for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
    if (attempt > 0) {
      await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
    }

    const status = await threadsGraphGet<{ status?: string; error_message?: string }>(
      `/${containerId}`,
      {
        access_token: accessToken,
        fields: "status,error_message",
      }
    );

    if (status.status === "FINISHED") return;
    if (status.status === "ERROR") {
      throw new ThreadsApiError(status.error_message ?? "媒體處理失敗");
    }
  }

  // Meta 建議至少等 30 秒，若狀態查不到仍嘗試發布
}

async function fetchPermalink(mediaId: string, accessToken: string): Promise<string | null> {
  try {
    const media = await threadsGraphGet<{ permalink?: string }>(`/${mediaId}`, {
      access_token: accessToken,
      fields: "permalink",
    });
    return media.permalink ?? null;
  } catch {
    return null;
  }
}
