import type { CollectionEntry } from "astro:content";
import { DEFAULT_LANG, type UserWebsite } from "@content/config";
import { getUsernameForLang } from "./get_username_for_lang";

type WebsiteUserData<W extends UserWebsite> = NonNullable<CollectionEntry<"users">["data"]["links"][W]>;

function getUserDataForWebsite<W extends UserWebsite>(user: CollectionEntry<"users">, website: W): WebsiteUserData<W> {
  const link = user.data.links[website];
  if (link) {
    return link;
  }
  throw new Error(`Cannot get "${website}" data for user "${user.id}"`);
}

const isPreferredWebsite = (user: CollectionEntry<"users">, website: UserWebsite) =>
  !!user.data.preferredLink && user.data.preferredLink == website;

/**
 * Format a user to the special string that references the user in a specified website -
 * for example, by adding the `@` in front of a Twitter handle.
 * Otherwise, it will be formatted as a Markdown link to the user's preferred link.
 * @param user User to format.
 * @param website Which website to format with.
 * The function will attempt to match the user's link for the given website,
 * or try to use any special formatting rules corresponding with the user's preferred link.
 * @param usernameFn Optional function that labels the user's preferred link.
 * By default, this will be a function that returns the username in English.
 * @returns
 */
export function getWebsiteLinkForUser(
  user: CollectionEntry<"users">,
  website: UserWebsite | undefined,
  usernameFn: (user: CollectionEntry<"users">) => string = (user) => getUsernameForLang(user, DEFAULT_LANG),
): string {
  if (website === "website") {
    website = undefined;
  }
  const { links, preferredLink } = user.data;
  switch (website) {
    case undefined:
      break;
    case "eka":
      if ("eka" in links) {
        return `:icon${getUserDataForWebsite(user, "eka").username}:`;
      }
      break;
    case "furaffinity":
      if ("furaffinity" in links) {
        return `:icon${getUserDataForWebsite(user, "furaffinity").username}:`;
      }
      break;
    case "weasyl":
      if ("weasyl" in links) {
        return `<!~${getUserDataForWebsite(user, "weasyl").username.replaceAll(" ", "")}>`;
      } else if (isPreferredWebsite(user, "furaffinity")) {
        return `<fa:${getUserDataForWebsite(user, "furaffinity").username.replaceAll("_", "")}>`;
      } else if (isPreferredWebsite(user, "inkbunny")) {
        return `<ib:${getUserDataForWebsite(user, "inkbunny").username}>`;
      } else if (isPreferredWebsite(user, "sofurry")) {
        return `<sf:${getUserDataForWebsite(user, "sofurry").username}>`;
      }
      break;
    case "inkbunny":
      if ("inkbunny" in links) {
        return `[iconname]${getUserDataForWebsite(user, "inkbunny").username}[/iconname]`;
      } else if (isPreferredWebsite(user, "furaffinity")) {
        return `[fa]${getUserDataForWebsite(user, "furaffinity").username}[/fa]`;
      } else if (isPreferredWebsite(user, "sofurry")) {
        return `[sf]${getUserDataForWebsite(user, "sofurry").username}[/sf]`;
      } else if (isPreferredWebsite(user, "weasyl")) {
        return `[weasyl]${getUserDataForWebsite(user, "weasyl").username}[/weasyl]`;
      }
      break;
    case "sofurry":
      if ("sofurry" in links) {
        return `:icon${getUserDataForWebsite(user, "sofurry").username}:`;
      } else if (isPreferredWebsite(user, "furaffinity")) {
        return `fa!${getUserDataForWebsite(user, "furaffinity").username}`;
      } else if (isPreferredWebsite(user, "inkbunny")) {
        return `ib!${getUserDataForWebsite(user, "inkbunny").username}`;
      }
      break;
    case "sofurrybeta":
      if ("sofurrybeta" in links) {
        return `@${links.sofurrybeta!.username}`;
      } else if ("sofurry" in links) {
        return `[${links.sofurry!.username}](${links.sofurry!.link})`;
      }
      break;
    case "twitter":
      if ("twitter" in links) {
        return `@${getUserDataForWebsite(user, "twitter").username}`;
      }
      break;
    case "mastodon":
      if ("mastodon" in links) {
        const { handle, instance } = getUserDataForWebsite(user, "mastodon");
        return `@${handle}@${instance}`;
      }
      break;
    case "bluesky":
      if ("bluesky" in links) {
        return `@${getUserDataForWebsite(user, "bluesky").username}`;
      }
      break;
    case "itaku":
      if ("itaku" in links) {
        return `@${getUserDataForWebsite(user, "itaku").username}`;
      }
      break;
    default:
      const unknown: never = website;
      throw new Error(`Unhandled export website "${unknown}"`);
  }
  if (preferredLink) {
    return `[${usernameFn(user)}](${links[preferredLink]!.link})`;
  }
  throw new Error(
    `No matching${website ? ` "${website}" ` : " "}link for user "${user.id}". (hint: consider setting their "preferredLink" property)`,
  );
}
