import { useCallback, useEffect, useRef, useState } from "react";
import clsx from "clsx";

import DynamicComponent from "@/components/dynamic-component";
import { toTitleCase } from "@/helpers/string";
import { useIsClient } from "@/hooks";

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

export const TYPOGRAPHY_TAGS: Record<string, keyof JSX.IntrinsicElements> = {
  "fluid-headline": "p",
  "heading-1": "h1",
  "heading-2": "h2",
  "heading-3": "h3",
  "heading-4": "h4",
  "heading-5": "h5",
  "heading-6": "h6",
  body: "p",
  small: "small",
  code: "code",
};

type TypographyKey = keyof typeof TYPOGRAPHY_TAGS;

interface TypographyAttributes {
  fontSize: string | number;
  lineHeight?: string | number;
}

type TypographyAttributesMap = Record<TypographyKey, TypographyAttributes>;

const typographyAttributesMap: TypographyAttributesMap = Object.fromEntries(
  Object.keys(TYPOGRAPHY_TAGS).map((key) => [
    key,
    { fontSize: "", lineHeight: "" },
  ]),
);

export const Typography = () => {
  const ref = useRef<HTMLDivElement>(null);
  const [typographyAttributes, setTypographyAttributes] =
    useState<TypographyAttributesMap>({ ...typographyAttributesMap });
  const isClient = useIsClient();

  const getAttributes = useCallback(() => {
    if (!isClient || !ref.current) return;

    const newAttributes = { ...typographyAttributesMap };

    Object.keys(TYPOGRAPHY_TAGS).forEach((key) => {
      const element = ref.current?.querySelector("." + key);
      if (element) {
        const computedStyle = getComputedStyle(element);
        const fontSize = Math.round(parseFloat(computedStyle.fontSize));
        const lineHeight = Math.round(parseFloat(computedStyle.lineHeight));
        newAttributes[key] = { fontSize, lineHeight };
      }
    });

    setTypographyAttributes(newAttributes);
  }, [isClient]);

  useEffect(() => {
    getAttributes();
    window.addEventListener("resize", getAttributes);
    return () => {
      window.removeEventListener("resize", getAttributes);
    };
  }, [getAttributes]);

  if (!isClient) return null;

  return (
    <div ref={ref} className={styles.debugTypography}>
      {Object.entries(typographyAttributes).map(([key, attrs]) => {
        const tag = TYPOGRAPHY_TAGS[key];
        return (
          <DynamicComponent
            key={key}
            className={clsx(key, styles.tag)}
            tag={tag}
          >
            <span className={key}>{toTitleCase(key)}</span>
            <span className={clsx(key, styles.attribute)}>
              {Object.entries(attrs).map(([attrKey, attrValue]) => (
                <span key={attrKey}>{attrValue}</span>
              ))}
            </span>
          </DynamicComponent>
        );
      })}
    </div>
  );
};
