import { NextResponse } from "next/server";
import { existsSync } from "fs";
import { prisma } from "@/lib/db";
import { getActiveAccountConnectionSettings } from "@/lib/account-connection-settings";
import { getOrCreateSettings } from "@/lib/user-settings";
import { assertAccountOwnedByUser } from "@/lib/auth/accounts";
import { authErrorResponse } from "@/lib/auth/api";
import { requireSessionUser } from "@/lib/auth/session";
import { requirePublishAuth } from "@/lib/services/threads-auth-guard";
import { factCheckDraft } from "@/lib/ai/fact-check";
import { parseProviderApiKeys } from "@/lib/ai/keys";
import {
  deleteDraftImages,
  draftImageAbsolutePath,
  draftImagePublicUrl,
  parseDraftImagePaths,
} from "@/lib/drafts/images";
import { ensureActiveSession, publish, SessionError } from "@/lib/threads-browser";
import {
  getAppBaseUrl,
  isPubliclyReachableUrl,
  publishViaThreadsApi,
} from "@/lib/threads-api";
import { getActiveThreadsCredentials } from "@/lib/services/threads-credentials";
import { trackAiTask } from "@/lib/jobs/track";

export const maxDuration = 120;

export async function POST(request: Request) {
  try {
    const user = await requireSessionUser();
    const authCheck = await requirePublishAuth();
    if (!authCheck.ok) {
      return NextResponse.json({ error: authCheck.error }, { status: 401 });
    }

    const { draftId } = (await request.json()) as { draftId?: string };
    if (!draftId) {
      return NextResponse.json({ error: "缺少 draftId" }, { status: 400 });
    }

    const draft = await prisma.draft.findUnique({ where: { id: draftId } });
    if (!draft) {
      return NextResponse.json({ error: "找不到草稿" }, { status: 404 });
    }
    if (draft.accountId) {
      await assertAccountOwnedByUser(user.id, draft.accountId);
    }

    const [settings, connection] = await Promise.all([
      getOrCreateSettings(),
      getActiveAccountConnectionSettings(),
    ]);
    const apiKeys = parseProviderApiKeys(settings.providerApiKeys);

    let topicLabel: string | undefined;
    if (draft.topicId) {
      const topic = await prisma.topic.findUnique({ where: { id: draft.topicId } });
      topicLabel = topic?.label;
    }

    const factCheck = await trackAiTask("發布前內容查核", () => factCheckDraft({
      text: draft.text,
      angle: draft.angle,
      searchTag: draft.searchTag,
      topicLabel,
      aiProvider: settings.aiProvider,
      aiModel: settings.aiModel,
      apiKeys,
    }));

    if (factCheck.isKnowledgeContent && !factCheck.passed) {
      await prisma.draft.update({
        where: { id: draftId },
        data: { factCheckResult: JSON.stringify(factCheck) },
      });
      return NextResponse.json(
        {
          error: "知識型內容未通過網路查證，請修正後再發布",
          factCheck,
        },
        { status: 422 }
      );
    }

    const draftImagePaths = parseDraftImagePaths(draft).filter((imagePath) =>
      existsSync(draftImageAbsolutePath(imagePath))
    );
    const hasImage = draftImagePaths.length > 0;
    // API 優先：帳號有連官方 API 就先用 API 發布；失敗或未連線才退回瀏覽器。
    const credentials = connection.publishViaApi
      ? await getActiveThreadsCredentials().catch(() => null)
      : null;

    type PublishOutcome = {
      success: boolean;
      permalink?: string;
      mediaId?: string;
      error?: string;
      debugRunId?: string;
      method?: string;
      warning?: string;
    };

    async function tryApiPublish(creds: NonNullable<typeof credentials>): Promise<PublishOutcome> {
      let imageUrl: string | undefined;
      let warning: string | undefined;

      if (hasImage) {
        const primaryPath = draftImagePaths[0];
        const publicUrl = draftImagePublicUrl(
          getAppBaseUrl(request, settings.appUrl),
          draftId!,
          primaryPath
        );
        if (isPubliclyReachableUrl(publicUrl)) {
          imageUrl = publicUrl;
          if (draftImagePaths.length > 1) {
            warning = "API 發布目前只會附上第一張配圖。";
          }
        } else {
          // 配圖需公開網址才能走 API；交給瀏覽器發布以保留配圖。
          return { success: false, method: "api", error: "配圖需公開網址，改用瀏覽器發布" };
        }
      }

      const apiResult = await publishViaThreadsApi(creds, { text: draft!.text, imageUrl });
      return {
        success: apiResult.success,
        permalink: apiResult.permalink,
        error: apiResult.error,
        method: "api",
        warning: apiResult.warning ?? warning,
      };
    }

    async function browserPublish(): Promise<PublishOutcome> {
      const session = await ensureActiveSession();
      const browserResult = await publish(
        session,
        draft!.text,
        draftImagePaths.map((imagePath) => draftImageAbsolutePath(imagePath))
      );
      return {
        success: browserResult.success,
        permalink: browserResult.permalink,
        error: browserResult.error,
        debugRunId: browserResult.debugRunId,
        method: "browser",
      };
    }

    let result: PublishOutcome | null = null;
    if (credentials) {
      try {
        const apiOutcome = await tryApiPublish(credentials);
        if (apiOutcome.success) result = apiOutcome;
      } catch {
        // 落入瀏覽器備援
      }
    }
    if (!result) {
      result = await browserPublish();
    }

    if (!result.success) {
      return NextResponse.json(
        {
          error: result.error ?? "發布失敗",
          method: result.method,
          debugRunId: result.debugRunId,
        },
        { status: 500 }
      );
    }

    const published = await prisma.$transaction(async (tx) => {
      const record = await tx.published.create({
        data: {
          accountId: draft.accountId,
          topicId: draft.topicId,
          externalId: result.mediaId,
          text: draft.text,
          angle: draft.angle,
          hook: draft.hook,
          rationale: draft.rationale,
          draftType: draft.draftType,
          permalink: result.permalink,
        },
      });

      await deleteDraftImages(draftImagePaths);
      await tx.draft.delete({ where: { id: draftId } });

      return record;
    });

    return NextResponse.json({
      published,
      permalink: result.permalink,
      factCheck,
      method: result.method,
      warning: result.warning,
    });
  } catch (error) {
    const authRes = authErrorResponse(error);
    if (authRes) return authRes;
    if (error instanceof SessionError) {
      return NextResponse.json({ error: error.message }, { status: 401 });
    }
    const message = error instanceof Error ? error.message : "發布失敗";
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
