"use client";

import { use, createContext } from "react";
import type { ExternalEmbed } from "@/data/queries";
import { LinkPreview } from "./LinkPreview";
import { BlueskyPostEmbed } from "./embeds/BlueskyPostEmbed";
import { loadTrailCard } from "@/app/loadTrailCard";
import {
  getBlueskyPost,
  getLinkMetadata,
  type BlueskyPost,
  type LinkMetadata,
} from "./utils/embed-resolver";
import "./embeds/TrailEmbed.css";
import "@/app/TrailCard.css";

type EmbedPromise = Promise<BlueskyPost | LinkMetadata | React.ReactElement | null>;
export type EmbedCache = Map<string, EmbedPromise>;
export const EmbedCacheContext = createContext<[EmbedCache | null, (c: EmbedCache) => void]>([
  null,
  () => {},
]);

type Props = {
  external: ExternalEmbed;
  onDelete?: () => void;
};

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/"))
  );
}

function getOrCreatePromise(uri: string, cache: EmbedCache): EmbedPromise {
  const existing = cache.get(uri);
  if (existing) return existing;

  let promise: EmbedPromise;
  if (isTrailUri(uri)) {
    promise = Promise.resolve().then(() => loadTrailCard(uri));
  } else if (isBlueskyPostUri(uri)) {
    promise = getBlueskyPost(uri);
  } else {
    promise = getLinkMetadata(uri);
  }

  cache.set(uri, promise);
  return promise;
}

export function StopEmbed({ external, onDelete }: Props) {
  const [cache] = use(EmbedCacheContext);
  if (!cache) throw new Error("StopEmbed must be used within EmbedCacheContext.Provider");

  const uri = external.uri;
  const isTrail = isTrailUri(uri);
  const isBluesky = isBlueskyPostUri(uri);
  const promise = getOrCreatePromise(uri, cache);
  const data = use(promise);

  if (!data) {
    return (
      <div className="BlueskyPostEmbed-container">
        <div className="BlueskyPostEmbed error">
          <div className="BlueskyPostEmbed-error">couldn't load embed</div>
        </div>
        {onDelete && (
          <button onClick={onDelete} className="BlueskyPostEmbed-deleteButton" title="remove link">
            ×
          </button>
        )}
      </div>
    );
  }

  if (isTrail) {
    if (onDelete) {
      return (
        <div className="TrailEmbed-container">
          {data as React.ReactElement}
          <button onClick={onDelete} className="TrailEmbed-deleteButton" title="remove link">
            ×
          </button>
        </div>
      );
    }
    return data as React.ReactElement;
  }

  if (isBluesky) {
    return <BlueskyPostEmbed post={data as BlueskyPost} onDelete={onDelete} />;
  }

  const metadata = data as LinkMetadata;
  const mergedExternal = {
    ...external,
    title: metadata.title || external.title,
    description: metadata.description || external.description,
    thumb: metadata.thumb || external.thumb,
  };

  return <LinkPreview external={mergedExternal} fallbackToUrl onDelete={onDelete} />;
}
