import { discoverAllComponents, loadAllComponentInfo, loadDesignEngineer } from "./cli/component-discovery.js";
import { generateText, tool, stepCountIs } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { openai } from "@ai-sdk/openai";
import { vercel } from "@ai-sdk/vercel";
import { groq } from "@ai-sdk/groq";
import { createGoogleGenerativeAI } from "@ai-sdk/google";
import pc from "picocolors";
import { g as getProviderForModel, a as getDefaultProvider, D as DEFAULT_MODEL, e as isSupportedGoogleModel, d as isSupportedGroqModel, c as isSupportedVercelModel, b as isSupportedOpenAIModel, i as isSupportedAnthropicModel } from "./models-DHa82GgN.js";
import { z } from "zod";
function getProviderOptionsForModel(model) {
  const provider = getProviderForModel(model);
  switch (provider) {
    case "anthropic":
      return {
        anthropic: {
          // Add default Anthropic options here if needed
          // e.g., cacheControl: { type: 'ephemeral' }
        }
      };
    case "openai": {
      if (model === "gpt-5.1") {
        return {
          openai: {
            reasoningEffort: "none"
          }
        };
      }
      return {
        openai: {
          reasoningEffort: "minimal"
        }
      };
    }
    case "groq":
      return {
        groq: {
          // Add default Groq options here if needed
          // e.g., parallelToolCalls: true
        }
      };
    case "google":
      return {
        google: {
          thinkingConfig: {
            thinkingLevel: "low"
            // Gemini 3 is new and we don't have types for this property yet.
            // TODO: Remove `as any` once we upgrade @ai-sdk/google types
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
          }
        }
      };
    case "vercel":
      return {};
    default: {
      const _exhaustiveCheck = provider;
      throw new Error(`Unknown provider: ${_exhaustiveCheck}`);
    }
  }
}
class LLMClient {
  hasAnthropicKey = false;
  hasOpenAIKey = false;
  hasVercelKey = false;
  hasGroqKey = false;
  hasGoogleKey = false;
  googleProvider = null;
  stepCounter = 0;
  constructor() {
    this.hasAnthropicKey = Boolean(process.env.ANTHROPIC_API_KEY);
    this.hasOpenAIKey = Boolean(process.env.OPENAI_API_KEY);
    this.hasVercelKey = Boolean(process.env.VERCEL_API_KEY);
    this.hasGroqKey = Boolean(process.env.GROQ_API_KEY);
    this.hasGoogleKey = Boolean(process.env.GOOGLE_GENERATIVE_AI_API_KEY);
    if (this.hasGoogleKey) {
      this.googleProvider = createGoogleGenerativeAI({
        apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY
      });
    }
    if (!this.hasAnthropicKey && !this.hasOpenAIKey && !this.hasVercelKey && !this.hasGroqKey && !this.hasGoogleKey) {
      console.warn(
        pc.yellow(
          "⚠️  No API keys found. Please set ANTHROPIC_API_KEY, OPENAI_API_KEY, VERCEL_API_KEY, GROQ_API_KEY, or GOOGLE_GENERATIVE_AI_API_KEY."
        )
      );
      console.warn(pc.gray("   To use AI features, export one of these:"));
      console.warn(pc.gray('   export ANTHROPIC_API_KEY="sk-ant-..."'));
      console.warn(pc.gray('   export OPENAI_API_KEY="sk-..."'));
      console.warn(pc.gray('   export VERCEL_API_KEY="..."'));
      console.warn(pc.gray('   export GROQ_API_KEY="gsk_..."'));
      console.warn(pc.gray('   export GOOGLE_GENERATIVE_AI_API_KEY="..."'));
    }
  }
  /**
   * Enhanced onStepFinish callback that provides readable, formatted output
   * for LLM generation steps including tool calls, token usage, and status.
   */
  onStepFinish = (step) => {
    this.stepCounter++;
    const stepNum = this.stepCounter;
    const hasToolCalls = step.toolCalls.length > 0;
    const hasText = step.text.length > 0;
    const hasReasoning = step.reasoningText && step.reasoningText.length > 0;
    const usage = step.usage;
    const finishReason = step.finishReason;
    const warnings = step.warnings;
    console.warn(pc.dim("─".repeat(60)));
    console.warn(
      pc.cyan(`Step ${stepNum}`) + (finishReason === "stop" ? ` ${pc.green("✓")}` : "")
    );
    if (hasToolCalls) {
      console.warn(pc.dim("  Tool calls:"));
      for (const toolCall of step.toolCalls) {
        const toolName = toolCall.toolName;
        const input = "input" in toolCall ? toolCall.input : void 0;
        const inputPreview = input !== void 0 ? typeof input === "object" && input !== null ? JSON.stringify(input).slice(0, 80) + (JSON.stringify(input).length > 80 ? "..." : "") : String(input) : "";
        console.warn(
          pc.gray(`    • ${pc.yellow(toolName)}(${pc.dim(inputPreview)})`)
        );
      }
    }
    if (step.toolResults.length > 0) {
      console.warn(pc.dim("  Tool results:"));
      for (const result of step.toolResults) {
        const toolName = result.toolName;
        const output = "output" in result ? result.output : void 0;
        const outputPreview = output !== void 0 ? typeof output === "object" && output !== null ? JSON.stringify(output).slice(0, 80) + (JSON.stringify(output).length > 80 ? "..." : "") : String(output) : "";
        console.warn(
          pc.gray(`    • ${pc.yellow(toolName)}: ${pc.dim(outputPreview)}`)
        );
      }
    }
    if (hasText) {
      const textPreview = step.text.length > 100 ? step.text.slice(0, 100) + "..." : step.text;
      console.warn(pc.dim("  Text:") + ` ${pc.gray(textPreview)}`);
    }
    if (hasReasoning) {
      const reasoningPreview = step.reasoningText.length > 100 ? step.reasoningText.slice(0, 100) + "..." : step.reasoningText;
      console.warn(pc.dim("  Reasoning:") + ` ${pc.gray(reasoningPreview)}`);
    }
    if (usage) {
      const promptTokens = "promptTokens" in usage ? usage.promptTokens : void 0;
      const completionTokens = "completionTokens" in usage ? usage.completionTokens : void 0;
      const totalTokens = "totalTokens" in usage ? usage.totalTokens : promptTokens !== void 0 && completionTokens !== void 0 ? promptTokens + completionTokens : void 0;
      if (totalTokens !== void 0) {
        const promptStr = promptTokens !== void 0 ? String(promptTokens) : "?";
        const completionStr = completionTokens !== void 0 ? String(completionTokens) : "?";
        console.warn(
          pc.dim("  Tokens:") + ` ${pc.blue(promptStr)} prompt + ${pc.blue(completionStr)} completion = ${pc.blue(String(totalTokens))} total`
        );
      } else if ("tokens" in usage) {
        console.warn(pc.dim("  Tokens:") + ` ${pc.blue(String(usage.tokens))}`);
      }
    }
    if (finishReason) {
      const reasonLabels = {
        stop: "completed",
        length: "max tokens",
        "tool-calls": "tool calls",
        "content-filter": "content filter",
        error: "error",
        other: "other"
      };
      const reasonLabel = reasonLabels[finishReason] || finishReason;
      console.warn(
        pc.dim("  Status:") + ` ${finishReason === "stop" ? pc.green(reasonLabel) : pc.yellow(reasonLabel)}`
      );
    }
    if (warnings && warnings.length > 0) {
      console.warn(pc.yellow("  Warnings:"));
      for (const warning of warnings) {
        const warningText = typeof warning === "string" ? warning : JSON.stringify(warning);
        console.warn(pc.yellow(`    ⚠ ${warningText}`));
      }
    }
  };
  /**
   * Generate text using AI SDK's unified interface
   */
  async generate(context, options = {}) {
    const provider = options.model ? getProviderForModel(options.model) : getDefaultProvider();
    this.validateProvider(provider);
    const model = this.getModel(options.model ?? DEFAULT_MODEL[provider]);
    try {
      const config = {
        model,
        prompt: context.prompt,
        onStepFinish: this.onStepFinish
      };
      if (options.temperature !== void 0) {
        config.temperature = options.temperature;
      }
      if (context.system) {
        config.system = context.system;
      }
      if (options.tools) {
        config.tools = options.tools;
      }
      if (options.toolChoice) {
        config.toolChoice = options.toolChoice;
      }
      if (options.stopWhen) {
        config.stopWhen = options.stopWhen;
      }
      if (options.providerOptions) {
        config.providerOptions = options.providerOptions;
      }
      const { text } = await generateText(config);
      return text;
    } catch (error) {
      if (error instanceof Error) {
        if (error.message.includes("API key")) {
          throw new Error(
            `${provider.toUpperCase()}_API_KEY environment variable is required`
          );
        }
        throw error;
      }
      throw new Error("Unknown error during LLM generation");
    }
  }
  /**
   * Validate that the provider has an API key
   */
  validateProvider(provider) {
    switch (provider) {
      case "anthropic":
        if (!this.hasAnthropicKey) {
          throw new Error("ANTHROPIC_API_KEY environment variable is required");
        }
        break;
      case "openai":
        if (!this.hasOpenAIKey) {
          throw new Error("OPENAI_API_KEY environment variable is required");
        }
        break;
      case "vercel":
        if (!this.hasVercelKey) {
          throw new Error("VERCEL_API_KEY environment variable is required");
        }
        break;
      case "groq":
        if (!this.hasGroqKey) {
          throw new Error("GROQ_API_KEY environment variable is required");
        }
        break;
      case "google":
        if (!this.hasGoogleKey) {
          throw new Error(
            "GOOGLE_GENERATIVE_AI_API_KEY environment variable is required"
          );
        }
        break;
      default: {
        const _exhaustiveCheck = provider;
        throw new Error(`Unknown provider: ${_exhaustiveCheck}`);
      }
    }
  }
  /**
   * Get the AI SDK model instance for a provider and model name
   */
  getModel(modelName) {
    const provider = getProviderForModel(modelName);
    switch (provider) {
      case "anthropic":
        if (!isSupportedAnthropicModel(modelName)) {
          throw new Error(`Unsupported Anthropic model: ${modelName}`);
        }
        return anthropic(modelName);
      case "openai":
        if (!isSupportedOpenAIModel(modelName)) {
          throw new Error(`Unsupported OpenAI model: ${modelName}`);
        }
        return openai(modelName);
      case "vercel":
        if (!isSupportedVercelModel(modelName)) {
          throw new Error(`Unsupported Vercel model: ${modelName}`);
        }
        return vercel(modelName);
      case "groq":
        if (!isSupportedGroqModel(modelName)) {
          throw new Error(`Unsupported Groq model: ${modelName}`);
        }
        return groq(modelName);
      case "google":
        if (!isSupportedGoogleModel(modelName)) {
          throw new Error(`Unsupported Google model: ${modelName}`);
        }
        if (!this.googleProvider) {
          throw new Error(
            "Google provider not initialized. GOOGLE_GENERATIVE_AI_API_KEY is required."
          );
        }
        return this.googleProvider(modelName);
      default: {
        const _exhaustiveCheck = provider;
        throw new Error(`Unsupported provider: ${_exhaustiveCheck}`);
      }
    }
  }
}
const listComponentsSchema = z.object({
  category: z.string().optional().describe(
    "Optional: Filter components by category (e.g., 'forms', 'data-display', 'layout')"
  )
});
tool({
  description: "Get a list of all available UI components with their categories and brief descriptions. Use this to explore what components exist before requesting detailed documentation.",
  inputSchema: listComponentsSchema,
  execute: async ({ category }) => {
    const components = discoverAllComponents();
    const filtered = category ? components.filter(
      (c) => c.category.toLowerCase() === category.toLowerCase()
    ) : components;
    return {
      total: filtered.length,
      components: filtered.map((c) => ({
        id: c.id,
        category: c.category,
        description: c.description || "No description available",
        importPath: c.importPath
      }))
    };
  }
});
const searchComponentsSchema = z.object({
  query: z.string().describe(
    "Search query (e.g., 'form input', 'data table', 'chart', 'navigation')"
  )
});
tool({
  description: "Search for components by keyword. Searches across component names and descriptions to find relevant components for your use case.",
  inputSchema: searchComponentsSchema,
  execute: async ({ query }) => {
    const components = discoverAllComponents();
    const searchTerm = query.toLowerCase();
    const matches = components.map((c) => {
      const nameMatch = c.name.toLowerCase().includes(searchTerm);
      const descMatch = c.description?.toLowerCase().includes(searchTerm);
      const categoryMatch = c.category.toLowerCase().includes(searchTerm);
      const idMatch = c.id?.toLowerCase().includes(searchTerm);
      let score = 0;
      if (nameMatch) score += 10;
      if (idMatch) score += 8;
      if (categoryMatch) score += 5;
      if (descMatch) score += 3;
      return { component: c, score };
    }).filter((item) => item.score > 0).sort((a, b) => b.score - a.score);
    return {
      query,
      found: matches.length,
      results: matches.map((item) => ({
        id: item.component.id,
        name: item.component.name,
        category: item.component.category,
        description: item.component.description || "No description available",
        importPath: item.component.importPath,
        relevance: item.score
      }))
    };
  }
});
const getComponentInfoSchema = z.object({
  componentIds: z.array(z.string()).describe(
    "Array of component IDs to fetch documentation for (e.g., ['button', 'input', 'card'])"
  )
});
const getComponentInfoTool = tool({
  description: "Get detailed documentation for specific components including full README content, usage examples, and prop definitions. Use this after identifying which components you need from list_components or search_components.",
  inputSchema: getComponentInfoSchema,
  execute: async ({ componentIds }) => {
    const allInfo = loadAllComponentInfo({ verbose: false });
    const results = {};
    for (const id of componentIds) {
      let info = allInfo[id];
      if (!info) {
        const infoByName = Object.values(allInfo).find(
          (component) => component.name === id
        );
        if (infoByName) {
          info = infoByName;
        }
      }
      if (!info) {
        results[id] = {
          found: false,
          error: `Component '${id}' not found`
        };
        continue;
      }
      results[id] = {
        found: true,
        info
      };
    }
    return {
      requested: componentIds.length,
      found: Object.values(results).filter((r) => r.found).length,
      components: results
    };
  }
});
const screenGenerator = async ({
  prompt,
  schema,
  model,
  validateCode = false,
  maxRetries = 2
}) => {
  const attempts = 0;
  const allValidationErrors = [];
  let response = null;
  let designEngineerPrompt;
  let code;
  while (attempts <= maxRetries) {
    const result = await generateCode(
      prompt,
      schema,
      model
    );
    response = result?.response || null;
    designEngineerPrompt = result?.prompt;
    code = response ? checkAndRemoveCodeFences(response) : null;
    if (!code || !validateCode) {
      break;
    }
    break;
  }
  return {
    prompt,
    schema,
    designEngineerPrompt,
    code: code || `
  import { ScreenWrapper } from "@glide/glide-ui/chrome";
  export default function YourScreen() {
    return (
      <ScreenWrapper>
        <div>Your screen content</div>
      </ScreenWrapper>
    );
  }
  `,
    validationErrors: allValidationErrors,
    validationAttempts: attempts
  };
};
const checkAndRemoveCodeFences = (text) => {
  if (!text) {
    return null;
  }
  let cleaned = text.trim();
  const importMatch = cleaned.match(
    /^\s*import\s+(?:(?:type\s+)?[{*\w]|["'])/m
  );
  const importIndex = importMatch ? importMatch.index : -1;
  if (importIndex === -1) {
    return cleaned;
  }
  cleaned = cleaned.substring(importIndex);
  let endMatch = cleaned.match(/<\/ScreenWrapper>\s*\);?\s*\}/);
  if (!endMatch) {
    endMatch = cleaned.match(/<\/ScreenWrapper>\s*\);/);
  }
  if (endMatch) {
    const endIndex = endMatch.index + endMatch[0].length;
    cleaned = cleaned.substring(0, endIndex);
  }
  return cleaned.trim();
};
const generateCode = async (prompt, schema, model, validationErrors, invalidCode) => {
  if (!prompt) {
    return null;
  }
  const template = loadDesignEngineer();
  let finalPrompt = template.replace("{{PROMPT}}", prompt);
  finalPrompt = schema ? finalPrompt.replace("{{SCHEMA}}", schema) : finalPrompt.replace("{{SCHEMA}}", "");
  const llmClient = new LLMClient();
  const response = await llmClient.generate(
    { prompt: finalPrompt },
    {
      model,
      maxTokens: 25e3,
      tools: {
        get_component_info: getComponentInfoTool
      },
      stopWhen: stepCountIs(10),
      providerOptions: getProviderOptionsForModel(model)
    }
  );
  return { response, prompt: finalPrompt };
};
export {
  LLMClient as L,
  checkAndRemoveCodeFences as c,
  screenGenerator as s
};
