"use server";

import "server-only";
import { cacheLife, cacheTag } from "next/cache";
import { Client, type l } from "@atproto/lex";
import * as getPostThread from "@/lib/lexicons/app/bsky/feed/getPostThread";
import * as feedDefs from "@/lib/lexicons/app/bsky/feed/defs";
import { loadTrailCardByUri } from "@/data/queries";
import { TrailCard } from "./TrailCard";
import { BlueskyPostEmbed } from "./at/(trail)/[handle]/trail/[rkey]/embeds/BlueskyPostEmbed";
import { LinkPreview } from "./at/(trail)/[handle]/trail/[rkey]/LinkPreview";
import { blueskyUrlToAtUri } from "./at/(trail)/[handle]/trail/[rkey]/utils/bluesky";

type BlueskyPost = feedDefs.ThreadViewPost;

type LinkMetadata = {
  uri: string;
  title: string;
  description: string;
  thumb?: string;
};

function isTrailUri(uri: string): boolean {
  return uri.includes("/app.sidetrail.trail/");
}

function isBlueskyPostUri(uri: string): boolean {
  return (
    uri.includes("/app.bsky.feed.post/") || (uri.includes("bsky.app") && uri.includes("/post/"))
  );
}

// Cached fetch for Bluesky posts - throws on failure
async function fetchBlueskyPost(atUri: string): Promise<BlueskyPost> {
  "use cache: redis";
  cacheTag(`embed:bsky:${atUri}`);
  cacheLife("days");

  const atprotoClient = new Client("https://public.api.bsky.app");
  const result = await atprotoClient.call(getPostThread.main, {
    uri: atUri as l.AtUri,
    depth: 0,
    parentHeight: 0,
  });
  if (feedDefs.threadViewPost.$check(result.thread)) {
    // Serialize to strip non-plain objects (like CID)
    return JSON.parse(JSON.stringify(result.thread)) as BlueskyPost;
  }
  throw new Error(`Invalid thread response for ${atUri}`);
}

// Cached fetch for link metadata - throws on failure
async function fetchLinkMetadata(url: string): Promise<LinkMetadata> {
  "use cache: redis";
  cacheTag(`embed:link:${url}`);
  cacheLife("days");

  const response = await fetch(`https://cardyb.bsky.app/v1/extract?url=${encodeURIComponent(url)}`);
  if (!response.ok) {
    throw new Error(`Failed to fetch link metadata: ${response.status}`);
  }

  const data = await response.json();
  return {
    uri: url,
    title: data.title || url,
    description: data.description || "",
    thumb: data.image || undefined,
  };
}

export async function loadEmbed(uri: string): Promise<React.ReactElement> {
  if (isTrailUri(uri)) {
    const trail = await loadTrailCardByUri(uri);
    if (!trail) throw new Error(`Trail not found: ${uri}`);
    return <TrailCard {...trail} />;
  }

  if (isBlueskyPostUri(uri)) {
    const atUri = uri.startsWith("at://")
      ? uri
      : uri.startsWith("http")
        ? blueskyUrlToAtUri(uri)
        : null;
    if (!atUri) throw new Error(`Invalid Bluesky URI: ${uri}`);

    const post = await fetchBlueskyPost(atUri);
    return <BlueskyPostEmbed post={post} />;
  }

  // Regular link
  const metadata = await fetchLinkMetadata(uri);
  return (
    <LinkPreview
      external={{
        uri: metadata.uri,
        title: metadata.title,
        description: metadata.description,
        thumb: metadata.thumb,
      }}
      fallbackToUrl
    />
  );
}
