import clsx from "clsx";
import { type ReactNode } from "react";
import { createBlockComponent, type IBlockProps } from "#components/meta";
import { Preformatted } from "#components/formatting";

import * as styles from "./description.module.scss";

export interface IDescriptionListProps extends IBlockProps<"dl"> {}

export interface IDescriptionSectionProps extends IBlockProps<"div"> {
  dKey?: ReactNode;
  dValue?: ReactNode;
  isHorizontal?: boolean;
  isValuePreformatted?: boolean;
}

export interface IDescriptionTermProps extends IBlockProps<"dt"> {}

export interface IDescriptionDetailsProps extends IBlockProps<"dd"> {}

export const DescriptionList = createBlockComponent(styles, DLComponent);
/**
 * Section of the details list.
 */
export const DescriptionSection = createBlockComponent(
  styles.section,
  DSComponent
);
export const DescriptionTerm = createBlockComponent(styles.term, DTComponent);
export const DescriptionDetails = createBlockComponent(undefined, DDComponent);

function DLComponent({ children, ...blockProps }: IDescriptionListProps) {
  return <dl {...blockProps}>{children}</dl>;
}

function DSComponent({
  dKey,
  dValue,
  isHorizontal = false,
  isValuePreformatted = false,
  className,
  children,
  ...blockProps
}: IDescriptionSectionProps) {
  const blockClass = clsx(
    className,
    (dKey || dValue) && styles.section_keyValue,
    isHorizontal && styles.section_horizontal
  );

  return (
    <div className={blockClass} {...blockProps}>
      {children ?? (
        <>
          <DescriptionTerm>{dKey}:</DescriptionTerm>
          <DescriptionDetails>
            {isValuePreformatted ? (
              <Preformatted>{dValue}</Preformatted>
            ) : (
              dValue
            )}
          </DescriptionDetails>
        </>
      )}
    </div>
  );
}

function DTComponent({ children, ...blockProps }: IDescriptionTermProps) {
  return <dt {...blockProps}>{children ?? "Unknown"}</dt>;
}

function DDComponent({ children, ...blockProps }: IDescriptionDetailsProps) {
  return <dd {...blockProps}>{children ?? "Unknown"}</dd>;
}
