import clsx from "clsx";
import Link from "next/link";
import { useRouter } from "next/router";

import CallToAction from "@/components/call-to-action";
import Icon from "@/components/icon";
import Image from "@/components/image";
import List from "@/components/list";
import { formatDate } from "@/helpers/date";
import { buildPageUrl } from "@/helpers/link";
import type { BasePost, News } from "@/types";

import styles from "./styles.module.scss";

export type ArticleCardVariant = "featured" | "standard" | "compact";

type ArticleCardProps = {
  variant?: ArticleCardVariant;
} & (BasePost | News);

const isNews = (props: ArticleCardProps): props is News => {
  return (props as News).publication !== undefined;
};

export default function ArticleCard({
  variant = "compact",
  ...props
}: ArticleCardProps) {
  const router = useRouter();

  const { type, title, date, tags } = props;

  const articleCardClasses = clsx(
    styles.articleCard,
    styles[type],
    styles[variant],
  );

  const renderTitle = <h3 className={styles.title}>{title}</h3>;
  const renderDate = date && <p className={styles.date}>{formatDate(date)}</p>;

  if (isNews(props)) {
    const { publication, url } = props;

    const ariaLabel = `Read the article ${
      publication
        ? `published by ${publication.name}`
        : "on an external website"
    } (opens in a new window)`;

    return (
      <article
        className={articleCardClasses}
        onClick={() => {
          window.open(url, "_blank", "noopener,noreferrer");
        }}
        aria-label={ariaLabel}
      >
        {renderDate}
        <Link
          href={url}
          target="_blank"
          rel="noopener noreferrer"
          prefetch={false}
        >
          {renderTitle}
        </Link>
        {publication && (
          <p className={styles.publication}>
            {publication.name}
            <Icon className={styles.icon} variant="arrowNortheast" />
          </p>
        )}
      </article>
    );
  }

  const { slug, coverImage, thumbnailImage, summary } = props;
  const url = buildPageUrl({ type: "post", slug });

  const ariaLabel = `Read the article titled "${title}"`;
  const image = coverImage && thumbnailImage && (
    <div className={styles.thumbnailImageContainer}>
      <Image image={thumbnailImage} layout={"intrinsic"} />
    </div>
  );

  const renderSummary = summary && <p className={styles.summary}>{summary}</p>;

  const renderTags = (
    <List
      className={styles.tags}
      items={
        tags && tags.length > 0
          ? tags.map((tag) => (
              <CallToAction
                key={tag.id}
                className={clsx(styles.tag, "tag")}
                href={buildPageUrl({
                  type: "post",
                  slug: `?tag=${tag.name.toLowerCase()}`,
                })}
              >
                {tag.name}
              </CallToAction>
            ))
          : []
      }
    />
  );

  const navigateToPage = () => {
    router.push(url);
  };

  const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
    event.preventDefault();
    navigateToPage();
  };

  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
    event.preventDefault();
    if (event.key === "Enter" || event.key === " ") navigateToPage();
  };

  if (variant === "standard") {
    return (
      <article
        className={articleCardClasses}
        role="button"
        tabIndex={0}
        onClick={handleClick}
        onKeyDown={handleKeyDown}
        aria-label={ariaLabel}
      >
        <div className={styles.image}>{image}</div>
        <div className={styles.content}>
          {renderDate}
          <Link href={url} prefetch={false}>
            {renderTitle}
          </Link>
          {renderSummary}
          {renderTags}
        </div>
      </article>
    );
  }

  return (
    <article
      className={articleCardClasses}
      role="button"
      tabIndex={0}
      onClick={handleClick}
      onKeyDown={handleKeyDown}
      aria-label={ariaLabel}
    >
      {image}
      <div className={styles.content}>
        {renderDate}
        <Link href={url} prefetch={false}>
          {renderTitle}
        </Link>
        {renderSummary}
        {renderTags}
      </div>
    </article>
  );
}
