import Head from 'next/head';
import Link from 'next/link';
import React, { createElement, useRef } from 'react';

interface ResponsiveSize {
  default?: string;
  sm?: string;
  md?: string;
  lg?: string;
  xl?: string;
  xxl?: string;
  extraLarge?: string;
}

interface TextProps {
  size?: string | ResponsiveSize;
  color?: string;
  weight?: 'normal' | 'bold' | 'lighter' | number;
  align?: 'left' | 'right' | 'center' | 'justify';
  variant?: 'small' | 'medium' | 'large';
  tag?: keyof JSX.IntrinsicElements;
  children: React.ReactNode;
  className?: string;
  lineHeight?: string;
  letterSpacing?: string;
  textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
  decoration?: 'none' | 'underline' | 'line-through';
  fontStyle?: 'normal' | 'italic';
  style?: React.CSSProperties;
  padding?: string;
  margin?: string;
  marginTop?: string;
  marginBottom?: string;
  marginLeft?: string;
  marginRight?: string;
  display?: 'block' | 'inline' | 'inline-block' | 'flex' | 'none';
  justifyContent?:
    | 'flex-start'
    | 'flex-end'
    | 'center'
    | 'space-between'
    | 'space-around';
  alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
  flexDirection?: 'row' | 'column';
  gap?: string;
  whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-wrap' | 'pre-line';
  overflow?: 'visible' | 'hidden' | 'scroll' | 'auto';
  textOverflow?: 'clip' | 'ellipsis';
  href?: string;
  target?: string;
  onClick?: () => void;
  hover?: {
    color?: string;
    background?: string;
    textDecoration?: string;
  };
  fontFamily?: string; // Allow passing a custom font family
}

// Define font size variants
const fontSizeVariants = {
  small: '12px',
  medium: '16px',
  large: '24px',
};

// Function to handle responsive font sizes
const getResponsiveFontSize = (size: string | ResponsiveSize) => {
  if (typeof size === 'string') {
    return `font-size: ${size};`;
  } else {
    return `
      font-size: ${size.default || 'inherit'};
      @media (min-width: 576px) { font-size: ${size.sm || size.default || 'inherit'}; }
      @media (min-width: 768px) { font-size: ${size.md || size.sm || size.default || 'inherit'}; }
      @media (min-width: 992px) { font-size: ${size.lg || size.md || size.sm || size.default || 'inherit'}; }
      @media (min-width: 1200px) { font-size: ${size.xl || size.lg || size.md || size.sm || size.default || 'inherit'}; }
      @media (min-width: 1400px) { font-size: ${size.xxl || size.xl || size.lg || size.md || size.sm || size.default || 'inherit'}; }
      @media (min-width: 1600px) { font-size: ${size.extraLarge || size.xxl || size.xl || size.lg || size.md || size.sm || size.default || 'inherit'}; }
    `;
  }
};

const generateUniqueClassName = () =>
  `text-${Math.random().toString(36).substring(2, 15)}`;

const Text: React.FC<TextProps> = ({
  size,
  color,
  weight,
  align,
  className,
  variant = 'medium',
  tag = 'p',
  children,
  lineHeight,
  letterSpacing,
  textTransform,
  decoration,
  fontStyle,
  style,
  padding,
  margin,
  marginTop,
  marginBottom = '0px',
  marginLeft,
  marginRight,
  display,
  justifyContent,
  alignItems,
  flexDirection,
  gap,
  whiteSpace,
  overflow,
  textOverflow,
  href,
  target,
  onClick,
  hover,
  fontFamily,
  ...props
}) => {
  const elementRef = useRef<HTMLDivElement | null>(null);
  const uniqueClassName = generateUniqueClassName();

  // Dynamically build the CSS string, only including styles that are provided by the user.
  let cssStyles = `.${uniqueClassName} {`;

  // Include responsive font size if it's defined
  cssStyles +=
    size || fontSizeVariants[variant || 'medium']
      ? getResponsiveFontSize(size || fontSizeVariants[variant || 'medium'])
      : '';

  // Conditionally add styles only if they are defined
  if (color) cssStyles += `color: ${color};`;
  if (weight) cssStyles += `font-weight: ${weight};`;
  if (lineHeight) cssStyles += `line-height: ${lineHeight};`;
  if (align) cssStyles += `text-align: ${align};`;
  if (letterSpacing) cssStyles += `letter-spacing: ${letterSpacing};`;
  if (textTransform) cssStyles += `text-transform: ${textTransform};`;
  if (decoration) cssStyles += `text-decoration: ${decoration};`;
  if (fontStyle) cssStyles += `font-style: ${fontStyle};`;
  if (padding) cssStyles += `padding: ${padding};`;
  if (margin) cssStyles += `margin: ${margin};`;
  if (marginTop) cssStyles += `margin-top: ${marginTop};`;
  if (marginBottom) cssStyles += `margin-bottom: ${marginBottom};`;
  if (marginLeft) cssStyles += `margin-left: ${marginLeft};`;
  if (marginRight) cssStyles += `margin-right: ${marginRight};`;
  if (display) cssStyles += `display: ${display};`;
  if (justifyContent) cssStyles += `justify-content: ${justifyContent};`;
  if (alignItems) cssStyles += `align-items: ${alignItems};`;
  if (flexDirection) cssStyles += `flex-direction: ${flexDirection};`;
  if (gap) cssStyles += `gap: ${gap};`;
  if (whiteSpace) cssStyles += `white-space: ${whiteSpace};`;
  if (overflow) cssStyles += `overflow: ${overflow};`;
  if (textOverflow) cssStyles += `text-overflow: ${textOverflow};`;
  if (fontFamily) cssStyles += `font-family: ${fontFamily};`;

  // End the style block
  cssStyles += `}`;

  // Add hover styles if provided
  if (hover) {
    cssStyles += `
      .${uniqueClassName}:hover {
        background: ${hover.background};
        color: ${hover.color};
        text-decoration: ${hover.textDecoration};
      }
    `;
  }

  // Add link styles if the component is a link
  if (tag === 'a' && href) {
    cssStyles += `
      .${uniqueClassName} a {
        color: inherit;
        text-decoration: none;
      }
    `;
  }

  // Apply the dynamically generated styles
  const commonProps = {
    className: uniqueClassName,
    style,
    onClick,
    ...props,
  };

  const Component = tag || 'p';

  return (
    <>
      <Head>
        <style>{cssStyles}</style>
      </Head>
      {href ? (
        <Link href={href} passHref legacyBehavior>
          {createElement(
            Component,
            {
              ...commonProps,
              ref: elementRef,
              target,
              style: { ...style, display: 'inline-block' }, // Ensure valid nesting
            },
            children
          )}
        </Link>
      ) : (
        createElement(
          Component,
          {
            ...commonProps,
            ref: elementRef,
          },
          children
        )
      )}
    </>
  );
};

export default Text;
