import React, { FC } from "react";
import { StyleSheet } from "@react-pdf/renderer";
import { merge } from "ts-deepmerge";
import path from "path";
import { buildComponentRegistry } from "../components/default-components.js";
import { baseSpecSchema } from "./base-spec-schema.js";
import { logger } from "../cli/logging.js";

export const generatePdfDocument = async (spec: any, file: string) => {
  const components = buildComponentRegistry(spec.config?.components || {});
  components.verifySpec(spec);

  const getComponent = ({ name }: { name: string }) => {
    const { component: Comp, defaultStyles } = components.getComponent(name);
    if (spec.styles?.[name])
      logger.debug(`Applying custom styles for {${name}}`);
    const styles = merge(defaultStyles, spec.styles?.[name] || {});
    const stylesheet = StyleSheet.create(styles);
    const resolvePath = (filePath: string) => {
      if (
        filePath.startsWith("http://") ||
        filePath.startsWith("https://") ||
        path.isAbsolute(filePath)
      ) {
        return filePath;
      }
      const resolved = `${path.resolve(path.join(path.dirname(file), filePath))}`;
      logger.debug(`File reference [${filePath}] resolved to [${resolved}]`);

      return resolved;
    };
    return (props: any) => (
      <Comp
        {...props}
        styles={stylesheet}
        spec={spec}
        resolvePath={resolvePath}
        getComponent={getComponent}
      />
    );
  };

  const ComponentRenderer: FC<{ name: string } & any> = ({
    name,
    ...props
  }) => {
    const Comp = getComponent({ name });
    return <Comp {...props} />;
  };

  const document = (
    <ComponentRenderer name="document">
      <ComponentRenderer name="page">
        <ComponentRenderer name="sectionOrder" />
        <ComponentRenderer name="pageNumbers" />
      </ComponentRenderer>
    </ComponentRenderer>
  );

  const fonts = baseSpecSchema.parse(spec).config?.fonts ?? [];

  return { document, fonts };
};
