const APPVIEW = "https://public.api.bsky.app/xrpc";

export interface BlueskyFacetFeature {
  $type: string;
  uri?: string;
  did?: string;
  tag?: string;
}

export interface BlueskyFacet {
  index: { byteStart: number; byteEnd: number };
  features: BlueskyFacetFeature[];
}

export interface BlueskyPost {
  uri: string;
  cid: string;
  author: {
    did: string;
    handle: string;
    displayName?: string;
    avatar?: string;
  };
  record: {
    text: string;
    createdAt: string;
    facets?: BlueskyFacet[];
  };
  likeCount?: number;
  repostCount?: number;
  replyCount?: number;
}

const POST_URL_RE =
  /^https?:\/\/bsky\.app\/profile\/([^/]+)\/post\/([a-z0-9]+)\/?$/i;

export function isBlueskyPostUrl(url: string): boolean {
  return POST_URL_RE.test(url);
}

export async function resolveHandle(handle: string): Promise<string | null> {
  if (handle.startsWith("did:")) return handle;
  try {
    const res = await fetch(
      `${APPVIEW}/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`,
      { next: { revalidate: 86400 } }
    );
    if (!res.ok) return null;
    const data: { did: string } = await res.json();
    return data.did;
  } catch {
    return null;
  }
}

export async function urlToAtUri(url: string): Promise<string | null> {
  const match = url.match(POST_URL_RE);
  if (!match) return null;
  const [, handleOrDid, rkey] = match;
  const did = await resolveHandle(handleOrDid);
  if (!did) return null;
  return `at://${did}/app.bsky.feed.post/${rkey}`;
}

export async function fetchPost(atUri: string): Promise<BlueskyPost | null> {
  try {
    const res = await fetch(
      `${APPVIEW}/app.bsky.feed.getPosts?uris=${encodeURIComponent(atUri)}`,
      { next: { revalidate: 3600 } }
    );
    if (!res.ok) return null;
    const data: { posts: BlueskyPost[] } = await res.json();
    return data.posts[0] ?? null;
  } catch {
    return null;
  }
}

export async function fetchPostByUrl(url: string): Promise<BlueskyPost | null> {
  const atUri = await urlToAtUri(url);
  if (!atUri) return null;
  return fetchPost(atUri);
}
