import { NextRequest, NextResponse } from "next/server";
import { ingestRawSubmission, rewriteSubmission } from "@/lib/ai/rewrite-pipeline";
import { findViolations } from "@/lib/disallowed-phrases-guard";
import { publishRawFallback } from "@/lib/ai/publish-raw-fallback";

export const runtime = "nodejs";
export const maxDuration = 300;

interface NativePayload {
  rawTitle: string;
  rawContent: string;
  rawHtml?: string;
  contributorEmail?: string;
  contributorName?: string;
  personaSlug?: string;
  source?: string;
  metadata?: Record<string, unknown>;
}

interface DistributePayload {
  submission_id?: string;
  property?: string;
  title: string;
  body: string;
  featured_image_url?: string | null;
  attachments?: unknown[];
  contributor?: {
    id?: string;
    email?: string;
    firm_name?: string;
    contact_name?: string;
    phone?: string;
  };
}

function bearerToken(req: NextRequest): string | null {
  const h = req.headers.get("authorization") || "";
  const m = h.match(/^Bearer\s+(.+)$/i);
  return m ? m[1].trim() : null;
}

function checkAuth(req: NextRequest): { ok: boolean; reason?: string } {
  const wantBearer = process.env.BB_INGEST_BEARER || "";
  const wantInternalKey = process.env.BB_INTERNAL_INGEST_KEY || "";
  if (!wantBearer && !wantInternalKey) {
    return { ok: false, reason: "ingest auth not configured (set BB_INGEST_BEARER)" };
  }
  if (wantBearer && bearerToken(req) === wantBearer) return { ok: true };
  if (wantInternalKey && (req.headers.get("x-internal-key") || "") === wantInternalKey) return { ok: true };
  return { ok: false, reason: "Unauthorized" };
}

function normalize(raw: any): NativePayload | null {
  if (!raw || typeof raw !== "object") return null;
  // Native shape: { rawTitle, rawContent, ... }
  if (typeof raw.rawTitle === "string" && typeof raw.rawContent === "string") {
    if (!raw.rawTitle.trim() || !raw.rawContent.trim()) return null;
    return raw as NativePayload;
  }
  // Distribute-rmp shape: { title, body, contributor: {...} }
  if (typeof raw.title === "string" && typeof raw.body === "string") {
    if (!raw.title.trim() || !raw.body.replace(/<[^>]*>/g, "").trim()) return null;
    const d = raw as DistributePayload;
    const contributorName = d.contributor?.contact_name || d.contributor?.firm_name || undefined;
    const contributorEmail = d.contributor?.email || undefined;
    return {
      rawTitle: d.title,
      rawContent: d.body.replace(/<[^>]*>/g, "").replace(/\s+/g, " ").trim(),
      rawHtml: d.body,
      contributorName,
      contributorEmail,
      source: "distribute-rmp",
      metadata: {
        distribute_submission_id: d.submission_id || null,
        property: d.property || null,
        featured_image_url: d.featured_image_url || null,
        attachments: d.attachments || [],
        contributor_firm: d.contributor?.firm_name || null,
        contributor_phone: d.contributor?.phone || null,
        contributor_id: d.contributor?.id || null,
      },
    };
  }
  return null;
}

export async function POST(req: NextRequest) {
  try {
    const auth = checkAuth(req);
    if (!auth.ok) {
      return NextResponse.json({ error: auth.reason || "Unauthorized" }, { status: 401 });
    }

    const raw = await req.json();
    const payload = normalize(raw);
    if (!payload) {
      return NextResponse.json(
        { error: "expected { rawTitle, rawContent } or { title, body }" },
        { status: 400 }
      );
    }

    // Reject submissions whose title or body contains a disallowed phrase
    // (competitor publications, banned exhibitors, etc.). Logged with the
    // violation list so the sender knows what to remove.
    const scanText = `${payload.rawTitle}\n${payload.rawContent}\n${payload.rawHtml || ""}`;
    const violations = await findViolations(scanText);
    if (violations.length > 0) {
      return NextResponse.json(
        {
          error: "Submission rejected: contains disallowed phrases",
          violations,
        },
        { status: 422 },
      );
    }

    const submissionId = await ingestRawSubmission(payload);
    const outcome = await rewriteSubmission({ submissionId, personaSlug: payload.personaSlug });

    // If the rewrite failed (Ollama 503 / model output bad), publish the raw
    // press release with a "rewrite pending" notice so the submission is at
    // least visible. Without this, PR-firm submissions disappear when Ollama
    // is saturated.
    let fallback: { wp_id: number; wp_slug: string } | null = null;
    if (outcome.status !== "succeeded") {
      const meta: any = payload.metadata || {};
      fallback = await publishRawFallback({
        submissionId,
        rawTitle: payload.rawTitle,
        rawHtml: payload.rawHtml || null,
        rawContent: payload.rawContent,
        contributorName: payload.contributorName || null,
        featuredImageUrl: typeof meta.featured_image_url === "string" ? meta.featured_image_url : null,
      });
    }

    return NextResponse.json({ ok: true, submissionId, outcome, raw_fallback: fallback });
  } catch (err: any) {
    return NextResponse.json({ error: err.message || String(err) }, { status: 500 });
  }
}
