import { puterChatComplete } from "../puter-inference.js";
import type { RenderResult, SocialPostBundle } from "./types.js";

// ─── Platform character limits ──────────────────────────────────────────────────

export const PLATFORM_CHAR_LIMITS: Record<string, number> = {
  "twitter-x":           280,
  "linkedin":           3000,
  "instagram-caption":  2200,
  "instagram-carousel":  300,  // per slide
};

// ─── Helpers ───────────────────────────────────────────────────────────────────

function buildSystemPrompt(platform: string, charLimit: number): string {
  if (platform === "instagram-carousel") {
    return [
      `You are a social media copywriter specializing in Instagram carousels.`,
      `Generate an Instagram carousel with 5-10 slides, each under ${charLimit} characters.`,
      `Also suggest 3-5 relevant hashtags.`,
      `Return JSON only:`,
      `{ "post": "intro caption", "slides": ["slide 1 text", "slide 2 text", "..."], "hashtags": ["#tag1", "#tag2"] }`,
      `No explanation, no markdown fences. Just the JSON object.`,
    ].join("\n");
  }

  return [
    `You are a social media copywriter.`,
    `Generate a ${platform} post under ${charLimit} characters.`,
    `Also suggest 3-5 relevant hashtags.`,
    `Return JSON only:`,
    `{ "post": "...", "hashtags": ["#tag1", "#tag2"] }`,
    `No explanation, no markdown fences. Just the JSON object.`,
  ].join("\n");
}

interface ParsedPost {
  post: string;
  hashtags: string[];
  slides?: string[];
}

function parseLlmJson(raw: string): ParsedPost {
  // Strip markdown fences if present
  const match =
    raw.match(/```json\s*([\s\S]*?)\s*```/) ||
    raw.match(/```\s*([\s\S]*?)\s*```/) ||
    raw.match(/(\{[\s\S]*\})/);

  const jsonStr = match ? match[1] : raw;
  const parsed = JSON.parse(jsonStr.trim()) as unknown;

  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
    throw new Error("LLM response is not a JSON object");
  }

  const obj = parsed as Record<string, unknown>;

  const post = typeof obj.post === "string" ? obj.post : "";
  const hashtags = Array.isArray(obj.hashtags)
    ? (obj.hashtags as unknown[]).filter((h): h is string => typeof h === "string")
    : [];
  const slides = Array.isArray(obj.slides)
    ? (obj.slides as unknown[]).filter((s): s is string => typeof s === "string")
    : undefined;

  return { post, hashtags, slides };
}

// ─── Main renderer ──────────────────────────────────────────────────────────────

export async function renderSocialPost(
  input: Record<string, unknown>,
): Promise<RenderResult> {
  const prompt =
    typeof input.prompt === "string" ? input.prompt : "a post about technology";
  const platform =
    typeof input.platform === "string" ? input.platform : "twitter-x";

  const charLimit = PLATFORM_CHAR_LIMITS[platform];
  if (charLimit === undefined) {
    throw new Error(
      `renderSocialPost: unknown platform "${platform}". ` +
        `Available: ${Object.keys(PLATFORM_CHAR_LIMITS).join(", ")}`,
    );
  }

  const systemPrompt = buildSystemPrompt(platform, charLimit);

  const rawResponse = await puterChatComplete([
    { role: "system", content: systemPrompt },
    { role: "user", content: prompt },
  ]);

  const parsed = parseLlmJson(rawResponse);

  const bundle: SocialPostBundle = {
    type: "social-post-bundle",
    platform,
    post: parsed.post,
    hashtags: parsed.hashtags,
    ...(parsed.slides !== undefined ? { slides: parsed.slides } : {}),
    charLimit,
  };

  return {
    filename: `social-${platform}.json`,
    contentType: "application/json",
    buffer: Buffer.from(JSON.stringify(bundle)),
  };
}
