import { getComponentInfo, loadDesignEngineer } from "./component-discovery.js";
import { L as LLMClient } from "../llm-client-E5_0H-oG.js";
import * as fs from "node:fs";
import path from "node:path";
import { MULTI_EXPORT_PACKAGES } from "./constants.js";
import { composeScreenPlan } from "./compose-screen-plan.js";
function formatComponentAsMarkdown(component) {
  const lines = [];
  if ("type" in component && component.type === "group") {
    const groupComponent = component;
    lines.push(`## ${groupComponent.name.toUpperCase()} Components
`);
    lines.push(`**Import from:** \`${groupComponent.importPath}\`
`);
    if (groupComponent.description) {
      lines.push(`${groupComponent.description}
`);
    }
    if (groupComponent.info) {
      lines.push(groupComponent.info);
      lines.push("\n");
    }
    lines.push("### Available components:\n");
    const componentsArray = Array.isArray(groupComponent.components) ? groupComponent.components.map((comp) => ({ id: comp.name, ...comp })) : Object.entries(groupComponent.components).map(([id, comp]) => ({
      id,
      ...comp
    }));
    componentsArray.forEach((comp) => {
      lines.push(`- **${comp.name}**`);
      lines.push(`  - Import: \`${comp.import}\``);
      if (comp.description) {
        lines.push(`  - Description: ${comp.description}`);
      }
    });
    lines.push(
      `
**Total:** ${componentsArray.length} components in ${groupComponent.name}`
    );
  } else {
    const singleComponent = component;
    lines.push(`## ${singleComponent.name}
`);
    if (singleComponent.import) {
      lines.push("### Usage:\n");
      lines.push("```typescript");
      lines.push(singleComponent.import);
      lines.push("```\n");
    }
    if (singleComponent.description) {
      lines.push("### Description:\n");
      lines.push(`${singleComponent.description}
`);
    }
    if (singleComponent.info) {
      lines.push("### Full Documentation:\n");
      lines.push(singleComponent.info);
      lines.push("\n");
    }
    if (singleComponent.props && Object.keys(singleComponent.props).length > 0) {
      lines.push("### Props:\n");
      lines.push("| Prop | Type | Required | Description |");
      lines.push("|------|------|----------|-------------|");
      Object.entries(singleComponent.props).forEach(([propName, propInfo]) => {
        const prop = propInfo;
        const type = prop.type || "any";
        const required = prop.required ? "Yes" : "No";
        const description = prop.description || "-";
        lines.push(
          `| \`${propName}\` | \`${type}\` | ${required} | ${description} |`
        );
      });
      lines.push("");
    }
    if (singleComponent.example) {
      lines.push("### Example:\n");
      lines.push("```tsx");
      lines.push(singleComponent.example);
      lines.push("```\n");
    }
  }
  return lines.join("\n");
}
const getDocumentationForComponent = (componentName) => {
  let component = getComponentInfo(componentName, { verbose: false });
  if (component && "type" in component && component.type === "group") {
    component = null;
  }
  if (!component) {
    for (const packageName of MULTI_EXPORT_PACKAGES) {
      const fullPath = `${packageName}/${componentName}`;
      const foundComponent = getComponentInfo(fullPath, { verbose: false });
      if (foundComponent && !("type" in foundComponent && foundComponent.type === "group")) {
        component = foundComponent;
        break;
      }
    }
  }
  if (!component) {
    return null;
  }
  return formatComponentAsMarkdown(component);
};
const screenGenerator = async ({
  prompt,
  schema,
  model,
  planningModel
}) => {
  const plan = await generatePlan(
    prompt,
    schema,
    planningModel || "gpt-5-nano"
  );
  const componentDocs = await fetchComponentDocumentation(plan);
  const { response, prompt: designEngineerPrompt } = await generateCode(plan, componentDocs, schema, model) || {};
  const codeWithoutCodeFences = response ? checkAndRemoveCodeFences(response) : null;
  return {
    prompt,
    schema,
    plan,
    designEngineerPrompt,
    componentDocs,
    code: codeWithoutCodeFences || `
  import { ScreenWrapper } from "@glide/glide-ui/chrome";
  export default function YourScreen() {
    return (
      <ScreenWrapper>
        <div>Your screen content</div>
      </ScreenWrapper>
    );
  }
  `
  };
};
const checkAndRemoveCodeFences = (text) => {
  if (!text) {
    return null;
  }
  let cleaned = text.trim();
  cleaned = cleaned.replace(
    /^```(?:typescript|tsx|ts|javascript|jsx|js|react)?\s*\n?/i,
    ""
  );
  cleaned = cleaned.replace(/\n?```\s*$/i, "");
  cleaned = cleaned.replaceAll(
    /\n```(?:typescript|tsx|ts|javascript|jsx|js|react)?\s*\n[\S\s]*?\n```\s*(?=\n|$)/gi,
    ""
  );
  cleaned = cleaned.replaceAll(
    /^\s*```(?:typescript|tsx|ts|javascript|jsx|js|react)?\s*$/gm,
    ""
  );
  cleaned = cleaned.replaceAll(/^\s*```\s*$/gm, "");
  cleaned = cleaned.replaceAll(/\n{3,}/g, "\n\n");
  return cleaned.trim();
};
const generateCode = async (plan, componentDocs, schema, model) => {
  if (!plan) {
    return null;
  }
  const exampleScreenCode = `
  import { ScreenWrapper } from "@glide/glide-ui/chrome";
  export default function YourScreen() {
    return (
      <ScreenWrapper>
        <div>Your screen content</div>
      </ScreenWrapper>
    );
  }
  `;
  const componentDocsText = Object.entries(componentDocs).map(([componentName, doc]) => `## ${componentName}

${doc}`).join("\n\n---\n\n");
  const template = loadDesignEngineer();
  let prompt = template.replace("{{PLAN}}", plan).replace(
    "{{COMPONENT_DOCS}}",
    componentDocsText || "No component documentation available."
  ).replace("{{EXAMPLE_CODE}}", exampleScreenCode);
  prompt = schema ? prompt.replace("{{SCHEMA}}", schema) : prompt.replace("{{SCHEMA}}", "");
  const llmClient = new LLMClient();
  await llmClient.initialize();
  const response = await llmClient.generate(
    { prompt },
    { model, maxTokens: 25e3 }
  );
  return { response, prompt };
};
const generatePlan = async (prompt, schema, model) => {
  const llmClient = new LLMClient();
  await llmClient.initialize();
  const designEngineerPrompt = composeScreenPlan(prompt, schema);
  const response = await llmClient.generate(
    { prompt: designEngineerPrompt },
    { model, maxTokens: 8e3 }
  );
  return response;
};
function toKebabCase(str) {
  return str.replaceAll(/([a-z])([A-Z])/g, "$1-$2").replaceAll(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
}
async function fetchComponentDocumentation(plan) {
  if (!plan) {
    return {};
  }
  const componentDocs = {};
  try {
    let cleanedPlan = plan.trim();
    cleanedPlan = cleanedPlan.replace(/^```(?:json|javascript|js)?\s*\n?/i, "");
    cleanedPlan = cleanedPlan.replace(/\n?```\s*$/i, "");
    cleanedPlan = cleanedPlan.replaceAll(
      /\n```(?:json|javascript|js)?\s*\n/gi,
      "\n"
    );
    cleanedPlan = cleanedPlan.replaceAll(/^\s*```\s*$/gm, "");
    const planData = JSON.parse(cleanedPlan.trim());
    const components = planData.components || [];
    if (!Array.isArray(components)) {
      return {};
    }
    for (const componentName of components) {
      if (typeof componentName !== "string") {
        continue;
      }
      const documentation = getDocumentationForComponent(componentName);
      if (!documentation) {
        console.warn(`No documentation found for ${componentName}`);
        continue;
      }
      componentDocs[componentName] = documentation;
    }
  } catch (error) {
    console.warn(
      "Failed to parse plan JSON, attempting to extract components from text:",
      error
    );
    const componentPattern = /components?\s*[:=]\s*\[(.*?)]/s;
    const match = plan.match(componentPattern);
    if (match) {
      const componentsStr = match[1];
      const componentNames = componentsStr.match(/'([^']+)'|"([^"]+)"/g)?.map((s) => s.slice(1, -1)) || [];
      for (const componentName of componentNames) {
        const readmePath = getComponentReadmePath(componentName);
        if (readmePath && fs.existsSync(readmePath)) {
          try {
            const readmeContent = fs.readFileSync(readmePath, "utf8");
            componentDocs[componentName] = readmeContent;
          } catch (error2) {
            console.warn(`Failed to read README for ${componentName}:`, error2);
          }
        }
      }
    }
  }
  return componentDocs;
}
function getComponentReadmePath(componentName) {
  if (componentName.includes("/")) {
    const [packageName] = componentName.split("/");
    const kebabPackage = toKebabCase(packageName);
    const packageDir = path.join(
      process.cwd(),
      `src/components/${kebabPackage}`
    );
    const readmePath2 = path.join(packageDir, "README.md");
    if (fs.existsSync(readmePath2)) {
      return readmePath2;
    }
    return null;
  }
  const kebabName = toKebabCase(componentName);
  const componentDir = path.join(process.cwd(), `src/components/${kebabName}`);
  const readmePath = path.join(componentDir, "README.md");
  return fs.existsSync(readmePath) ? readmePath : null;
}
export {
  screenGenerator
};
