import URL from "url";
import React from "react";

import { Link as GatsbyLink } from "gatsby";
import { OutboundLink } from "gatsby-plugin-google-gtag";

import type { Maybe } from "../types";
import { notEmpty, type RequireOnlyOne } from "../utils";

import "../styles/Link.css";

export type ISiteLinkProps = React.HTMLProps<HTMLAnchorElement>;

const ensureTrailingSlash = (url: string): string => {
  // @ts-ignore
  const _url = new URL.parse(url);
  // eslint-disable-next-line no-useless-escape
  _url.pathname =
    _url.pathname.replace(/^\/?([^\\/]+(?:\/[^\/]+)*)\/?$/, "/$1/") || "/";

  return `${_url.pathname ?? ""}${_url.search ?? ""}${_url.hash ?? ""}`;
};

export const SiteLink = React.forwardRef<HTMLAnchorElement, ISiteLinkProps>(
  ({ ...props }, ref) => {
    const internal = /^\.?\/(?!\/)/.test(props.href || "");

    if ((props.href || "").startsWith("#")) {
      return <a {...props} />;
    }
    if (internal) {
      // @ts-ignore
      props.to = ensureTrailingSlash(props.href as string);
      props.ref = ref;
    }
    const LinkComponent: React.ElementType = internal
      ? GatsbyLink
      : OutboundLink;
    // @ts-expect-error
    return <LinkComponent {...props} />;
  },
);

interface ILinkObject {
  readonly slug: string;
  readonly title: Maybe<string>;
  readonly handle: Maybe<string>;
}
type MyLinkObject = RequireOnlyOne<ILinkObject, "title" | "handle">;

type ILinkListType = readonly MyLinkObject[];

interface ILinkListProps {
  links: ILinkListType;
  Component?: React.FC;
  componentProps?: React.ComponentProps<typeof SiteLink>;
}

export const LinkList: React.FC<ILinkListProps> = ({
  links,
  Component = SiteLink,
  componentProps,
}) => {
  if (!links || links.length < 1) {
    return <></>;
  }
  return (
    <>
      {links.filter(notEmpty).map((obj: MyLinkObject, idx: number) => [
        idx > 0 && ", ",
        <Component href={obj.slug} key={idx} {...componentProps}>
          {obj.title || obj.handle}
        </Component>,
      ])}
    </>
  );
};

interface ILinkBoxProps {
  href: string;
  linkProps?: React.ComponentProps<typeof SiteLink>;
  boxProps?: React.HTMLProps<HTMLDivElement> & { style?: any };
}

export const LinkBox: React.FC<ILinkBoxProps> = ({
  children,
  href,
  linkProps = {},
  boxProps = {},
}) => (
  <SiteLink
    href={href}
    className="link-box"
    style={linkProps.style}
    {...linkProps}
  >
    <div style={boxProps.style} {...boxProps}>
      {children}
    </div>
  </SiteLink>
);
