'use strict';

const layerUtils = require('../../../../lib/ui-builder/store/layer-utils.cjs');
require('react');
const types = require('../../types.cjs');

const renderTemplate = (template, data) => {
  return template.replace(/<%~\s*it\.(\w+)\s*%>/g, (_, key) => {
    return data[key] ?? "";
  });
};
const toValidIdentifier = (input) => {
  let identifier = input.trim();
  if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(identifier)) {
    return identifier;
  }
  identifier = identifier.replace(/[^a-zA-Z0-9_$]/g, " ").split(" ").filter((word) => word.length > 0).map((word, index) => {
    if (index === 0) {
      return word.charAt(0).toLowerCase() + word.slice(1);
    }
    return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
  }).join("");
  if (identifier && !/^[a-zA-Z_$]/.test(identifier)) {
    identifier = "_" + identifier;
  }
  if (!identifier || !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(identifier)) {
    identifier = "variable";
  }
  return identifier;
};
const generateVariableIdentifiers = (variables) => {
  const identifierMap = /* @__PURE__ */ new Map();
  const usedIdentifiers = /* @__PURE__ */ new Set();
  variables.forEach((variable) => {
    const baseIdentifier = toValidIdentifier(variable.name);
    let identifier = baseIdentifier;
    let counter = 1;
    while (usedIdentifiers.has(identifier)) {
      identifier = `${baseIdentifier}${counter}`;
      counter++;
    }
    usedIdentifiers.add(identifier);
    identifierMap.set(variable.id, identifier);
  });
  return identifierMap;
};
const pageLayerToCode = (page, componentRegistry, variables = []) => {
  const layers = page.children;
  const { mode, colorTheme, borderRadius, ...restOfProps } = page.props;
  const variableIdentifiers = generateVariableIdentifiers(variables);
  const pageProps = generatePropsString(restOfProps, variables, variableIdentifiers);
  const imports = /* @__PURE__ */ new Set();
  const collectImports = (layer) => {
    const componentDefinition = componentRegistry[layer.type];
    if (componentDefinition && componentDefinition.from) {
      imports.add(
        createFromString(componentDefinition.from, layer.type, componentDefinition.isFromDefaultExport)
      );
      if (layerUtils.hasLayerChildren(layer)) {
        layer.children.forEach(collectImports);
      }
    }
  };
  let code = "";
  if (Array.isArray(layers)) {
    layers.forEach(collectImports);
    code = layers.map((layer) => generateLayerCode(layer, 1, variables, variableIdentifiers)).join("\n");
  } else {
    code = `{"${layers}"}`;
  }
  const importsString = Array.from(imports).join("\n");
  const variablePropsInterface = generateVariablePropsInterface(variables, variableIdentifiers);
  const variablePropsParam = variables.length > 0 ? "{ variables }: PageProps" : "";
  const finalCode = renderTemplate(reactComponentTemplate, {
    imports: importsString,
    variablePropsInterface,
    variablePropsParam,
    pageProps,
    children: code.split("\n").map((line) => `    ${line}`).join("\n")
  });
  return finalCode;
};
const generateLayerCode = (layer, indent = 0, variables = [], variableIdentifiers) => {
  if (!variableIdentifiers && variables.length > 0) {
    variableIdentifiers = generateVariableIdentifiers(variables);
  }
  const indentation = "  ".repeat(indent);
  let childrenCode = "";
  if (layerUtils.hasLayerChildren(layer) && layer.children.length > 0) {
    childrenCode = layer.children.map((child) => generateLayerCode(child, indent + 1, variables, variableIdentifiers)).join("\n");
  } else if (typeof layer.children === "string") {
    childrenCode = `${indentation}${"  "}{${JSON.stringify(layer.children)}}`;
  }
  if (childrenCode) {
    return `${indentation}<${layer.type}${generatePropsString(
      layer.props,
      variables,
      variableIdentifiers
    )}>
${childrenCode}
${indentation}</${layer.type}>`;
  } else {
    return `${indentation}<${layer.type}${generatePropsString(layer.props, variables, variableIdentifiers)} />`;
  }
};
const generatePropsString = (props, variables = [], variableIdentifiers) => {
  if (!variableIdentifiers && variables.length > 0) {
    variableIdentifiers = generateVariableIdentifiers(variables);
  }
  const propsArray = Object.entries(props).filter(([_, value]) => value !== void 0).map(([key, value]) => {
    let propValue;
    if (types.isVariableReference(value)) {
      const variable = variables.find((v) => v.id === value.__variableRef);
      if (variable && variableIdentifiers) {
        propValue = `{variables.${variableIdentifiers.get(variable.id)}}`;
      } else {
        propValue = `{undefined}`;
      }
    } else if (typeof value === "string") {
      propValue = `"${value}"`;
    } else if (typeof value === "number") {
      propValue = `{${value}}`;
    } else {
      propValue = `{${JSON.stringify(value)}}`;
    }
    return `${key}=${propValue}`;
  });
  return propsArray.length > 0 ? ` ${propsArray.join(" ")}` : "";
};
const generateVariablePropsInterface = (variables, variableIdentifiers) => {
  if (variables.length === 0) return "";
  if (!variableIdentifiers) {
    variableIdentifiers = generateVariableIdentifiers(variables);
  }
  const variableTypes = variables.map((variable) => {
    let tsType = "any";
    switch (variable.type) {
      case "string":
        tsType = "string";
        break;
      case "number":
        tsType = "number";
        break;
      case "boolean":
        tsType = "boolean";
        break;
    }
    return `    ${variableIdentifiers.get(variable.id)}: ${tsType};`;
  }).join("\n");
  return `interface PageProps {
  variables: {
${variableTypes}
  };
}

`;
};
const reactComponentTemplate = `import React from "react";
<%~ it.imports %>

<%~ it.variablePropsInterface %>const Page = (<%~ it.variablePropsParam %>) => {
  return (
    <div<%~ it.pageProps %>>
<%~ it.children %>
    </div>
  );
};

export default Page;
`;
const createFromString = (from, layerType, isFromDefaultExport) => {
  if (isFromDefaultExport) {
    return `import ${layerType} from "${from}";`;
  }
  return `import { ${layerType} } from "${from}";`;
};

exports.generateLayerCode = generateLayerCode;
exports.generatePropsString = generatePropsString;
exports.pageLayerToCode = pageLayerToCode;
