import React from "react";
import {
  Body,
  UnorderedList,
  OrderedList,
  Button,
  Container,
  Heading,
  Heading2,
  Heading3,
  Heading4,
  Heading5,
  Heading6,
  ImageElement,
  Section,
  Span,
  Anchor,
  Bold,
  Marquee,
} from "../IndividualComponents";
import { Some } from "../utils/Some";
import { getClassName } from "../utils/getClassName";
import { getBackgroundImage } from "../utils/getBackgroundImage";

export type Data = {
  type: string;
  content?: Data[];
  attributes?: Record<string, string>;
};

export type Content = {
  id: string;
  textvalue: string;
};

const getContentValue = (content: Content[], id: any) => {
  if (Some(content) && content.length !== 0) {
    const mappedContent = content.find((c) => c.id === id);
    //@ts-ignore
    return Some(mappedContent) ? mappedContent.textvalue : null;
  }
  return null;
};

const getTextValue = (content: any) => {
  return Some(content) ? (content[0] as unknown as string) : "";
};

export const generateReactElements = (data: Data, content: Content[]) => {
  // const selectedTheme = Some(theme) ? theme : "light";
  if (typeof data === "string") {
    return data;
  }
  if (data.type === "div") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    return (
      <Container className={className ?? ""} content={content} id={attributes.id}>
        {children}
      </Container>
    );
  } else if (data.type === "section") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const backgroundImageUrl = getBackgroundImage(attributes.style);

    if (Some(backgroundImageUrl) && backgroundImageUrl !== "") {
      return (
        <section
          className={className}
          style={{
            background: `url(${backgroundImageUrl})`,
            backgroundRepeat: "no-repeat",
            backgroundSize: "cover",
            backgroundPosition: "center",
          }}
        >
          {children.map((child, index) => (
            <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
          ))}
        </section>
      );
    }

    return (
      <Section className={className} content={content}>
        {children}
      </Section>
    );
  } else if (data.type === "h1") {
    const attributes = data.attributes || {};
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      if (color) {
        return (
          <Heading
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Heading
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];
      if (color) {
        return <Heading className={className ?? ""} id={attributes.id} text={text} color={color} />;
      }

      return <Heading className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <h1 className={className} id={attributes.id}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </h1>
    );
  } else if (data.type === "h2") {
    const attributes = data.attributes || {};
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      if (color) {
        return (
          <Heading2
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Heading2
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];

      if (color) {
        return (
          <Heading2 className={className ?? ""} id={attributes.id} text={text} color={color} />
        );
      }

      return <Heading2 className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <h2 className={className} id={attributes.id}>
        {data?.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </h2>
    );
  } else if (data.type === "h3") {
    const attributes = data.attributes || {};
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      if (color) {
        return (
          <Heading3
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Heading3
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];

      if (color) {
        return (
          <Heading3 className={className ?? ""} id={attributes.id} text={text} color={color} />
        );
      }

      return <Heading3 className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <h3 className={className} id={attributes.id}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </h3>
    );
  } else if (data.type === "h4") {
    const attributes = data.attributes || {};
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      if (color) {
        return (
          <Heading4
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Heading4
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];

      if (color) {
        return (
          <Heading4 className={className ?? ""} id={attributes.id} text={text} color={color} />
        );
      }

      return <Heading4 className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <h4 className={className} id={attributes.id}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </h4>
    );
  } else if (data.type === "h5") {
    const attributes = data.attributes || {};
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      if (color) {
        return (
          <Heading5
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Heading5
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];

      if (color) {
        return (
          <Heading5 className={className ?? ""} id={attributes.id} text={text} color={color} />
        );
      }

      return <Heading5 className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <h5 className={className} id={attributes.id}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </h5>
    );
  } else if (data.type === "h6") {
    const attributes = data.attributes || {};
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      if (color) {
        return (
          <Heading6
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Heading6
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];

      if (color) {
        return (
          <Heading6 className={className ?? ""} id={attributes.id} text={text} color={color} />
        );
      }

      return <Heading6 className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <h6 className={className} id={attributes.id}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </h6>
    );
  } else if (data.type === "p") {
    const attributes = data.attributes || {};

    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      const color = fontColor ? fontColor[1] : null;
      if (color) {
        return (
          <Body
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Body
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      const color = fontColor ? fontColor[1] : null;
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];
      if (color) {
        return <Body className={className ?? ""} id={attributes.id} text={text} color={color} />;
      }

      return <Body className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <p className={className} id={attributes.id}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </p>
    );
  } else if (data.type === "span") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);
    const fontFamily = /font-family\s*:\s*([^;]*)/.exec(styleAttribute);
    const fontSize = /font-size\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    const font = fontFamily ? fontFamily[1] : undefined;
    const fontsize = fontSize ? fontSize[1] : undefined;

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      const color = fontColor ? fontColor[1] : null;
      if (color) {
        return (
          <Span
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Span
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    //@ts-ignore
    if (typeof data?.content[0] === "string") {
      //@ts-ignore
      const text = Some(data.content) ? (data?.content[0] as unknown as string) : "";
      if (color) {
        return <Span className={className ?? ""} id={attributes.id} text={text} color={color} />;
      }
      return (
        <Span
          className={className ?? ""}
          id={attributes.id}
          text={text}
          font={font}
          fontsize={fontsize}
        />
      );
    }

    return (
      <span className={className} style={{ display: "inline" }}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </span>
    );
  } else if (data.type === "ul") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const filteredChildern = children.filter((element) => !/^[\s\n]+$/.test(element));

    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <UnorderedList content={content} className={className ?? ""}>
        {filteredChildern}
      </UnorderedList>
    );
  } else if (data.type === "img") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <ImageElement
        src={attributes.src}
        alt={attributes.alt}
        id={attributes.id}
        env={attributes.env}
        className={className ?? ""}
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
      />
    );
  } else if (data.type === "button") {
    const attributes = data.attributes || {};
    const text = data.content ? (data?.content[0] as unknown as string) : "";
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    if (Some(attributes.onclick)) {
      const onClickFunc = attributes.onclick.split("(")[0];

      //@ts-ignore
      const executeFunction = (funcName, event) => {
        if (typeof window[funcName] === "function") {
          //@ts-ignore
          window[funcName](event);
        } else {
          console.error(`Function ${funcName} does not exist`);
        }
      };

      //@ts-ignore
      const handleButtonClick = (funcName, event) => {
        // Execute function based on the button clicked
        executeFunction(funcName, event);
      };

      return (
        <Button
          className={className ?? ""}
          {...attributes}
          text={text}
          onClick={(event) => handleButtonClick(onClickFunc, event)}
        />
      );
    }

    return <Button className={className ?? ""} text={text} {...attributes} />;
  } else if (data.type === "a") {
    const attributes = data.attributes || {};
    const href = attributes.href || "#";
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    // const text = getContentValue(content, attributes.id) ?? (data?.content[0] as unknown as string);

    //return  <a href="#">Learn More</a>
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    //@ts-ignore

    const regex = /^\n\s*$/;
    //@ts-ignore
    const updatedContents = data?.content?.filter((item) => !regex.test(item));
    //@ts-ignore
    if (typeof updatedContents?.[0] === "string") {
      onclick;
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? updatedContents?.[0];
      if (color) {
        return (
          <a className={className} style={{ color }} {...attributes}>
            {text}
          </a>
        );
      }

      return (
        <a className={className} {...attributes}>
          {text}
        </a>
      );
    }

    if (Some(attributes.onclick)) {
      const onClickFunc = attributes.onclick.split("(")[0];
      //@ts-ignore
      const executeFunction = (funcName) => {
        if (typeof window[funcName] === "function") {
          //@ts-ignore
          window[funcName]();
        } else {
          console.error(`Function ${funcName} does not exist`);
        }
      };
      //@ts-ignore
      const handleButtonClick = (funcName) => {
        // Execute function based on the button clicked
        executeFunction(funcName);
      };

      return (
        <Anchor
          className={className}
          href={href.replace(/'/g, "%27")}
          role={attributes.role}
          dataSlide={attributes["data-slide"]}
          data={data.content}
          content={content}
          onClick={() => handleButtonClick(onClickFunc)}
        />
      );
    }
    const target = href.startsWith("https") ? "_blank" : undefined;
    return (
      <a
        className={className}
        href={href.replace(/'/g, "%27")}
        role={attributes.role}
        data-slide={attributes["data-slide"]}
        target={target}
      >
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </a>
    );
  } else if (data.type === "b") {
    const attributes = data.attributes || {};
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const styleAttribute = attributes.style;
    const fontColor = /color\s*:\s*([^;]*)/.exec(styleAttribute);

    const color = fontColor ? fontColor[1] : null;
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (data.content === undefined) {
      if (color) {
        return (
          <Bold
            className={className ?? ""}
            id={attributes.id}
            text={getContentValue(content, attributes.id) ?? ""}
            color={color}
          />
        );
      }

      return (
        <Bold
          className={className ?? ""}
          id={attributes.id}
          text={getContentValue(content, attributes.id) ?? ""}
        />
      );
    }

    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    if (typeof data.content[0] === "string") {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      //@ts-ignore
      const text = getContentValue(content, attributes.id) ?? data?.content[0];

      if (color) {
        return <Bold className={className ?? ""} id={attributes.id} text={text} color={color} />;
      }

      return <Bold className={className ?? ""} id={attributes.id} text={text} />;
    }

    return (
      <b className={className} id={attributes.id}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </b>
    );
  } else if (data.type === "u") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <u className={className} style={{ whiteSpace: "pre-wrap" }}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </u>
    );
  } else if (data.type === "i") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <i style={{ whiteSpace: "pre-wrap" }} className={className}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </i>
    );
  } else if (data.type === "strong") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    //@ts-ignore
    const text = getContentValue(content, attributes.id) ?? (data?.content[0] as string);

    return (
      <strong style={{ whiteSpace: "pre-wrap" }} className={className}>
        {text}
      </strong>
    );
  } else if (data.type === "em") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    //@ts-ignore
    const text = getContentValue(content, attributes.id) ?? (data?.content[0] as string);

    return (
      <em className={className} style={{ whiteSpace: "pre-wrap" }}>
        {text}
      </em>
    );
  } else if (data.type === "s") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <s className={className} style={{ whiteSpace: "pre-wrap" }}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </s>
    );
  } else if (data.type === "blockquote") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <blockquote className={className}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </blockquote>
    );
    //TODO: check with rich text editor for code blocks
  } else if (data.type === "pre") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <pre className="" spellCheck="false" {...attributes}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </pre>
    );
  } else if (data.type === "ol") {
    const attributes = data.attributes || {};
    const children = data.content || [];
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const filteredChildern = children.filter((element) => !/^[\s\n]+$/.test(element));

    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    return (
      <OrderedList content={content} className={className ?? ""}>
        {filteredChildern}
      </OrderedList>
    );
  } else if (data.type === "video") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const children = data.content || [];
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    //@ts-ignore
    const sources = children.filter((element) => !/^[\s\n]+$/.test(element));

    // Remove the unnecessary sources links
    if (Some(attributes.src)) {
      const { src, ...updatedAttributes } = attributes;
      return (
        <video {...updatedAttributes}>
          <source src={attributes.src} type={attributes.type} />
        </video>
      );
    }

    return (
      <video {...attributes}>
        <source src={sources[0]?.attributes?.src} type={sources[0]?.attributes?.type} />
      </video>
    );
  } else if (data.type === "form") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const children = data.content || [];

    return (
      <form className={className} {...attributes}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </form>
    );
  } else if (data.type === "label") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    //@ts-ignore
    const text = getContentValue(content, attributes.id) ?? (data?.content[0] as string);

    return (
      <label className={className} {...attributes}>
        {text}
      </label>
    );
  } else if (data.type === "input") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const children = data.content || [];

    return <input className={className} {...attributes}></input>;
  } else if (data.type === "textarea") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    //@ts-ignore
    const text = getContentValue(content, attributes.id) ?? (data?.content?.[0] as string);

    return (
      <textarea className={className} {...attributes}>
        {text}
      </textarea>
    );
  } else if (data.type === "iframe") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    const src = attributes.src || getContentValue(content, attributes.id) || undefined;

    return <iframe className={className} id={attributes.id} src={src} {...attributes} />;
  } else if (data.type === "br") {
    //@ts-ignore
    return <br />;
  } else if (data.type === "marquee") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const content = data.content || [];
    const textvalue = content.toString();

    return (
      <Marquee children={textvalue} className={className} id={attributes.id} {...attributes} />
    );
  } else if (data.type === "header") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const children = data.content || [];

    return (
      <header className={className} {...attributes}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </header>
    );
  } else if (data.type === "footer") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const children = data.content || [];

    return (
      <footer className={className} {...attributes}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </footer>
    );
  } else if (data.type === "nav") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const children = data.content || [];

    return (
      <nav className={className} {...attributes}>
        {children.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </nav>
    );
  } else if (data.type === "picture") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);
    const children = data.content || [];

    const sources = children.filter((child) => child.type === "source");
    const imgElement = children.find((child) => child.type === "img");

    return (
      <picture className={className ?? ""}>
        {sources.map((source, index) => (
          <source key={index} srcSet={source.attributes?.srcset} media={source.attributes?.media} />
        ))}
        {imgElement &&
          (() => {
            const attributes = imgElement.attributes || {};
            const className = Some(attributes.class)
              ? getClassName(attributes.class)
              : getClassName(attributes.classname);

            return (
              <ImageElement
                src={attributes.src}
                alt={attributes.alt ?? ""}
                id={attributes.id}
                env={attributes.env}
                className={className ?? ""}
                sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
              />
            );
          })()}
      </picture>
    );
  } else if (data.type === "table") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    const children = data.content || [];
    // Extract the header content (thead)
    const theadData = children.find((child) => child.type === "thead");

    const tbodyData = children.find((child) => child.type === "tbody");
    return (
      <table className={className} {...attributes}>
        {theadData && (
          <thead>
            {theadData.content?.map((row, rowIndex) => (
              <tr key={rowIndex}>
                {row.content?.map((headerCell, cellIndex) => {
                  const cellContent = headerCell.content?.map((child) =>
                    typeof child === "string" ? child : generateReactElements(child, content),
                  );

                  return <th key={cellIndex}>{cellContent}</th>;
                })}
              </tr>
            ))}
          </thead>
        )}
        {tbodyData && (
          <tbody>
            {tbodyData.content?.map((row, rowIndex) => (
              <tr key={rowIndex}>
                {row.content?.map((cell, cellIndex) => {
                  const cellContent = cell.content?.map((child) =>
                    typeof child === "string" ? child : generateReactElements(child, content),
                  );

                  return <td key={cellIndex}>{cellContent}</td>;
                })}
              </tr>
            ))}
          </tbody>
        )}
      </table>
    );
  } else if (data.type === "figure") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    // Separate figcaption from other content
    const figCaption = data.content?.find((child) => child.type === "figcaption");
    const otherContent = data.content?.filter((child) => child.type !== "figcaption");

    return (
      <figure className={className} {...attributes}>
        {/* Render all non-caption content like img */}
        {otherContent?.map((child, index) => {
          if (child.type === "img") {
            const imgAttributes = child.attributes || {};
            const imgClassName = Some(imgAttributes.class)
              ? getClassName(imgAttributes.class)
              : getClassName(imgAttributes.classname);

            return (
              <ImageElement
                key={index}
                src={imgAttributes.src}
                alt={imgAttributes.alt}
                id={imgAttributes.id}
                env={attributes.env}
                className={imgClassName ?? ""}
                sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
              />
            );
          }
          return (
            <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
          );
        })}
        {/* Render the figcaption */}
        {figCaption && (
          <figcaption>
            {figCaption.content?.map((child, index) =>
              typeof child === "string" ? (
                <React.Fragment key={index}>{child}</React.Fragment>
              ) : (
                <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
              ),
            )}
          </figcaption>
        )}
      </figure>
    );
  } else if (data.type === "main") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <main className={className} {...attributes}>
        {data.content?.map((child, index) => (
          <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
        ))}
      </main>
    );
  } else if (data.type === "hr") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return <hr className={className ?? ""} {...attributes} />;
  } else if (data.type === "select") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    return (
      <select className={className ?? ""} {...attributes}>
        {data.content?.map((child, index) =>
          child.type === "option" ? (
            <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
          ) : null,
        )}
      </select>
    );
  } else if (data.type === "option") {
    const attributes = data.attributes || {};
    const className = Some(attributes.class)
      ? getClassName(attributes.class)
      : getClassName(attributes.classname);

    const value = attributes.value || "";

    return (
      <option value={value} className={className ?? ""} {...attributes}>
        {data.content?.map((child, index) =>
          typeof child === "string" ? (
            <React.Fragment key={index}>{child}</React.Fragment>
          ) : (
            <React.Fragment key={index}>{generateReactElements(child, content)}</React.Fragment>
          ),
        )}
      </option>
    );
  } else {
    return null;
  }
};
