import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import { useState, useEffect, forwardRef, useImperativeHandle, useCallback } from "react";
import { Box, Text } from "ink";
import * as fs from "fs";
import * as path from "path";
import { spawn } from "child_process";
import { useAnimationTick } from "../../../hooks/useAnimationTick.js";
import { BRAILLE_SPINNER_FRAMES } from "../../../constants/spinnerFrames.js";
import {
  saveCustomModel,
  getAllInstalledModels,
  addInstalledModel,
  removeInstalledModel,
  getModelsDirectory,
  formatSize,
  getDextoGlobalPath
} from "@dexto/agent-management";
import { promises as fsPromises } from "fs";
import {
  getAllLocalModels,
  getLocalModelById,
  getRecommendedLocalModels,
  downloadModel,
  isNodeLlamaCppInstalled
} from "@dexto/core";
import { SetupInfoBanner } from "./shared/index.js";
const MAX_VISIBLE_ITEMS = 8;
const LocalModelWizard = forwardRef(
  function LocalModelWizard2({ isVisible, onComplete, onClose }, ref) {
    const [step, setStep] = useState("select-model");
    const [models, setModels] = useState([]);
    const [installedIds, setInstalledIds] = useState(/* @__PURE__ */ new Set());
    const [selectedIndex, setSelectedIndex] = useState(0);
    const [scrollOffset, setScrollOffset] = useState(0);
    const [showAllModels, setShowAllModels] = useState(false);
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState(null);
    const [nodeLlamaInstalled, setNodeLlamaInstalled] = useState(true);
    const [nodeLlamaChecked, setNodeLlamaChecked] = useState(false);
    const [isInstallingNodeLlama, setIsInstallingNodeLlama] = useState(false);
    const [installConfirmIndex, setInstallConfirmIndex] = useState(0);
    const [refreshTrigger, setRefreshTrigger] = useState(0);
    const installSpinnerTick = useAnimationTick({
      enabled: isInstallingNodeLlama,
      intervalMs: 80
    });
    const installSpinnerFrame = installSpinnerTick % BRAILLE_SPINNER_FRAMES.length;
    const [customPath, setCustomPath] = useState("");
    const [displayName, setDisplayName] = useState("");
    const [selectedModelId, setSelectedModelId] = useState(null);
    const [selectedModelPath, setSelectedModelPath] = useState(null);
    const [downloadProgress, setDownloadProgress] = useState(
      null
    );
    const [downloadError, setDownloadError] = useState(null);
    const [installedOptionIndex, setInstalledOptionIndex] = useState(0);
    const [selectedInstalledModel, setSelectedInstalledModel] = useState(null);
    const [isDeleting, setIsDeleting] = useState(false);
    useEffect(() => {
      if (!isVisible) return;
      setStep("select-model");
      setSelectedIndex(0);
      setScrollOffset(0);
      setShowAllModels(false);
      setCustomPath("");
      setDisplayName("");
      setSelectedModelId(null);
      setSelectedModelPath(null);
      setDownloadProgress(null);
      setDownloadError(null);
      setInstalledOptionIndex(0);
      setSelectedInstalledModel(null);
      setIsDeleting(false);
      setError(null);
      setIsInstallingNodeLlama(false);
      setInstallConfirmIndex(0);
      setNodeLlamaChecked(false);
    }, [isVisible]);
    useEffect(() => {
      if (!isVisible) return;
      let cancelled = false;
      const loadData = async () => {
        setIsLoading(true);
        try {
          if (!nodeLlamaChecked || !nodeLlamaInstalled) {
            const installed = await isNodeLlamaCppInstalled();
            if (!cancelled) {
              setNodeLlamaInstalled(installed);
              setNodeLlamaChecked(true);
              if (!installed) {
                setStep("install-node-llama");
                setIsLoading(false);
                return;
              }
            }
          }
          const installedModels = await getAllInstalledModels();
          const installedSet = new Set(installedModels.map((m) => m.id));
          if (!cancelled) {
            setInstalledIds(installedSet);
          }
          const registryModels = showAllModels ? getAllLocalModels() : getRecommendedLocalModels();
          const options = registryModels.map((m) => ({
            id: m.id,
            name: m.name,
            description: m.description,
            sizeBytes: m.sizeBytes,
            isInstalled: installedSet.has(m.id),
            minVRAM: m.minVRAM
          }));
          if (!cancelled) {
            setModels(options);
            setIsLoading(false);
          }
        } catch (err) {
          if (!cancelled) {
            setError(err instanceof Error ? err.message : "Failed to load models");
            setIsLoading(false);
          }
        }
      };
      void loadData();
      return () => {
        cancelled = true;
      };
    }, [isVisible, showAllModels, refreshTrigger, nodeLlamaInstalled, nodeLlamaChecked]);
    useEffect(() => {
      const itemCount = models.length + 3;
      if (selectedIndex < scrollOffset) {
        setScrollOffset(selectedIndex);
      } else if (selectedIndex >= scrollOffset + MAX_VISIBLE_ITEMS) {
        setScrollOffset(
          Math.min(selectedIndex - MAX_VISIBLE_ITEMS + 1, itemCount - MAX_VISIBLE_ITEMS)
        );
      }
    }, [selectedIndex, models.length, scrollOffset]);
    const handleSelectModel = useCallback(
      async (modelId) => {
        if (installedIds.has(modelId)) {
          const modelInfo = getLocalModelById(modelId);
          const installedModels = await getAllInstalledModels();
          const installedModel = installedModels.find((m) => m.id === modelId);
          setSelectedInstalledModel({
            id: modelId,
            filePath: installedModel?.filePath || "",
            displayName: modelInfo?.name || modelId
          });
          setInstalledOptionIndex(0);
          setStep("installed-options");
          return;
        }
        setSelectedModelId(modelId);
        setStep("downloading");
        setDownloadProgress(null);
        setDownloadError(null);
        try {
          const result = await downloadModel(modelId, {
            targetDir: getModelsDirectory(),
            events: {
              onProgress: (progress) => {
                setDownloadProgress(progress);
              },
              onComplete: () => {
              },
              onError: (_id, err) => {
                setDownloadError(err.message);
              }
            }
          });
          const modelInfo = getLocalModelById(modelId);
          const installedModel = {
            id: modelId,
            filePath: result.filePath,
            sizeBytes: result.sizeBytes,
            downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
            source: "huggingface",
            filename: modelInfo?.filename || path.basename(result.filePath)
          };
          if (result.sha256) {
            installedModel.sha256 = result.sha256;
          }
          await addInstalledModel(installedModel);
          onComplete({
            name: modelId,
            provider: "local",
            displayName: modelInfo?.name || modelId
          });
        } catch (err) {
          setDownloadError(err instanceof Error ? err.message : "Download failed");
        }
      },
      [installedIds, onComplete]
    );
    const handleCustomPathSubmit = useCallback(async () => {
      const trimmedPath = customPath.trim();
      if (!trimmedPath) {
        setError("File path is required");
        return;
      }
      if (!trimmedPath.toLowerCase().endsWith(".gguf")) {
        setError("File must have .gguf extension");
        return;
      }
      const expandedPath = trimmedPath.startsWith("~") ? trimmedPath.replace("~", process.env.HOME || "") : trimmedPath;
      if (!path.isAbsolute(expandedPath)) {
        setError("Please enter an absolute path (starting with / or ~)");
        return;
      }
      if (!fs.existsSync(expandedPath)) {
        setError(`File not found: ${trimmedPath}`);
        return;
      }
      setSelectedModelPath(expandedPath);
      const filename = path.basename(expandedPath, ".gguf");
      setDisplayName(filename);
      setStep("display-name");
      setError(null);
    }, [customPath]);
    const handleDisplayNameSubmit = useCallback(async () => {
      if (!selectedModelPath) return;
      const trimmedName = displayName.trim();
      const filename = path.basename(selectedModelPath, ".gguf");
      const modelId = filename.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").substring(0, 50);
      const model = {
        name: modelId,
        provider: "local",
        filePath: selectedModelPath,
        displayName: trimmedName || filename
      };
      try {
        await saveCustomModel(model);
        onComplete(model);
      } catch (err) {
        setError(err instanceof Error ? err.message : "Failed to save model");
      }
    }, [selectedModelPath, displayName, onComplete]);
    const handleInstalledOption = useCallback(async () => {
      if (!selectedInstalledModel) return;
      if (installedOptionIndex === 0) {
        onComplete({
          name: selectedInstalledModel.id,
          provider: "local",
          displayName: selectedInstalledModel.displayName
        });
      } else {
        setIsDeleting(true);
        setError(null);
        try {
          if (selectedInstalledModel.filePath) {
            try {
              await fsPromises.unlink(selectedInstalledModel.filePath);
            } catch (err) {
              const nodeErr = err;
              if (nodeErr.code !== "ENOENT") {
                throw err;
              }
            }
          }
          await removeInstalledModel(selectedInstalledModel.id);
          setInstalledIds((prev) => {
            const next = new Set(prev);
            next.delete(selectedInstalledModel.id);
            return next;
          });
          setStep("select-model");
          setSelectedInstalledModel(null);
        } catch (err) {
          setError(err instanceof Error ? err.message : "Failed to delete model");
        } finally {
          setIsDeleting(false);
        }
      }
    }, [selectedInstalledModel, installedOptionIndex, onComplete]);
    const installNodeLlamaCpp = useCallback(async () => {
      const depsDir = getDextoGlobalPath("deps");
      if (!fs.existsSync(depsDir)) {
        fs.mkdirSync(depsDir, { recursive: true });
      }
      const packageJsonPath = path.join(depsDir, "package.json");
      if (!fs.existsSync(packageJsonPath)) {
        fs.writeFileSync(
          packageJsonPath,
          JSON.stringify(
            {
              name: "dexto-deps",
              version: "1.0.0",
              private: true,
              description: "Native dependencies for Dexto"
            },
            null,
            2
          )
        );
      }
      return new Promise((resolve) => {
        const child = spawn("npm", ["install", "node-llama-cpp"], {
          stdio: ["ignore", "ignore", "pipe"],
          // stdin ignored, stdout ignored (not needed), stderr piped for errors
          cwd: depsDir
        });
        let stderr = "";
        child.stderr?.on("data", (data) => {
          stderr += data.toString();
        });
        child.on("close", (code) => {
          if (code === 0) {
            resolve(true);
          } else {
            setError(`Installation failed: ${stderr.slice(0, 200)}`);
            resolve(false);
          }
        });
        child.on("error", (err) => {
          setError(`Installation failed: ${err.message}`);
          resolve(false);
        });
      });
    }, []);
    const handleInstallConfirm = useCallback(async () => {
      if (installConfirmIndex === 1) {
        onClose();
        return;
      }
      setIsInstallingNodeLlama(true);
      setError(null);
      const success = await installNodeLlamaCpp();
      setIsInstallingNodeLlama(false);
      if (success) {
        setNodeLlamaInstalled(true);
        setNodeLlamaChecked(true);
        setStep("select-model");
        setIsLoading(true);
        setRefreshTrigger((prev) => prev + 1);
      } else {
        setError(
          (prev) => prev || "Installation failed. Check your internet connection and try again."
        );
      }
    }, [installConfirmIndex, installNodeLlamaCpp, onClose]);
    useImperativeHandle(
      ref,
      () => ({
        handleInput: (input, key) => {
          if (!isVisible) return false;
          if (key.escape) {
            if (step === "custom-path" || step === "display-name" || step === "installed-options") {
              setStep("select-model");
              setError(null);
              setSelectedInstalledModel(null);
              return true;
            }
            if (step === "downloading" && downloadError) {
              setStep("select-model");
              setDownloadError(null);
              return true;
            }
            onClose();
            return true;
          }
          if (step === "install-node-llama") {
            if (isInstallingNodeLlama) return true;
            if (key.upArrow || key.downArrow) {
              setInstallConfirmIndex((prev) => prev === 0 ? 1 : 0);
              return true;
            }
            if (key.return) {
              void handleInstallConfirm();
              return true;
            }
            return true;
          }
          if (step === "select-model") {
            const itemCount = models.length + 3;
            if (key.upArrow) {
              setSelectedIndex((prev) => prev > 0 ? prev - 1 : itemCount - 1);
              return true;
            }
            if (key.downArrow) {
              setSelectedIndex((prev) => prev < itemCount - 1 ? prev + 1 : 0);
              return true;
            }
            if (key.return) {
              const showAllIndex = models.length;
              const customPathIndex = models.length + 1;
              const backIndex = models.length + 2;
              if (selectedIndex === backIndex) {
                onClose();
                return true;
              }
              if (selectedIndex === showAllIndex) {
                setShowAllModels(!showAllModels);
                setSelectedIndex(0);
                setScrollOffset(0);
                return true;
              }
              if (selectedIndex === customPathIndex) {
                setStep("custom-path");
                setCustomPath("");
                setError(null);
                return true;
              }
              const model = models[selectedIndex];
              if (model) {
                void handleSelectModel(model.id);
              }
              return true;
            }
            return true;
          }
          if (step === "custom-path") {
            if (key.return) {
              void handleCustomPathSubmit();
              return true;
            }
            if (key.backspace || key.delete) {
              setCustomPath((prev) => prev.slice(0, -1));
              setError(null);
              return true;
            }
            if (input && !key.ctrl && !key.meta) {
              setCustomPath((prev) => prev + input);
              setError(null);
              return true;
            }
            return true;
          }
          if (step === "display-name") {
            if (key.return) {
              void handleDisplayNameSubmit();
              return true;
            }
            if (key.backspace || key.delete) {
              setDisplayName((prev) => prev.slice(0, -1));
              return true;
            }
            if (input && !key.ctrl && !key.meta) {
              setDisplayName((prev) => prev + input);
              return true;
            }
            return true;
          }
          if (step === "installed-options") {
            if (isDeleting) return true;
            if (key.upArrow || key.downArrow) {
              setInstalledOptionIndex((prev) => prev === 0 ? 1 : 0);
              return true;
            }
            if (key.return) {
              void handleInstalledOption();
              return true;
            }
            return true;
          }
          if (step === "downloading") {
            return true;
          }
          return false;
        }
      }),
      [
        isVisible,
        step,
        models,
        selectedIndex,
        showAllModels,
        customPath,
        displayName,
        downloadError,
        isDeleting,
        installedOptionIndex,
        handleSelectModel,
        handleCustomPathSubmit,
        handleDisplayNameSubmit,
        handleInstalledOption,
        handleInstallConfirm,
        isInstallingNodeLlama,
        installConfirmIndex,
        onClose
      ]
    );
    if (!isVisible) return null;
    if (step === "install-node-llama") {
      const options = [
        { label: "Yes", description: "Install now (may take 1-2 minutes)" },
        { label: "No", description: "Go back" }
      ];
      return /* @__PURE__ */ jsxs(
        Box,
        {
          flexDirection: "column",
          borderStyle: "round",
          borderColor: "yellow",
          paddingX: 1,
          marginTop: 1,
          children: [
            /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "Dependency Required" }) }),
            /* @__PURE__ */ jsx(Text, { children: "Local model execution requires node-llama-cpp." }),
            /* @__PURE__ */ jsx(Text, { color: "gray", children: "This will compile native bindings for your system." }),
            isInstallingNodeLlama ? /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
              /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
                BRAILLE_SPINNER_FRAMES[installSpinnerFrame],
                " Installing node-llama-cpp (compiling native bindings)..."
              ] }) }),
              /* @__PURE__ */ jsx(Text, { color: "gray", children: "This may take 1-2 minutes." })
            ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsx(Box, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { children: "Install node-llama-cpp now?" }) }),
              options.map((option, idx) => /* @__PURE__ */ jsxs(Box, { children: [
                /* @__PURE__ */ jsxs(Text, { color: idx === installConfirmIndex ? "cyan" : "white", children: [
                  idx === installConfirmIndex ? "\u276F " : "  ",
                  option.label
                ] }),
                idx === installConfirmIndex && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
                  " - ",
                  option.description
                ] })
              ] }, option.label))
            ] }),
            error && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "red", children: error }) }),
            /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: isInstallingNodeLlama ? "Please wait..." : "\u2191\u2193 navigate \u2022 Enter select \u2022 Esc cancel" }) })
          ]
        }
      );
    }
    if (isLoading) {
      return /* @__PURE__ */ jsx(
        Box,
        {
          flexDirection: "column",
          borderStyle: "round",
          borderColor: "green",
          paddingX: 1,
          marginTop: 1,
          children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Loading models..." })
        }
      );
    }
    if (step === "downloading") {
      return /* @__PURE__ */ jsxs(
        Box,
        {
          flexDirection: "column",
          borderStyle: "round",
          borderColor: "green",
          paddingX: 1,
          marginTop: 1,
          children: [
            /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "Downloading Model" }) }),
            downloadError ? /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsxs(Text, { color: "red", children: [
                "Download failed: ",
                downloadError
              ] }),
              /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Press Esc to go back" }) })
            ] }) : downloadProgress ? /* @__PURE__ */ jsxs(Fragment, { children: [
              /* @__PURE__ */ jsxs(Text, { children: [
                selectedModelId,
                ": ",
                downloadProgress.percentage.toFixed(1),
                "%"
              ] }),
              /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
                formatSize(downloadProgress.bytesDownloaded),
                " /",
                " ",
                formatSize(downloadProgress.totalBytes),
                downloadProgress.speed ? ` \u2022 ${formatSize(downloadProgress.speed)}/s` : "",
                downloadProgress.eta ? ` \u2022 ETA: ${Math.round(downloadProgress.eta)}s` : ""
              ] }),
              /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
                /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2588".repeat(
                  Math.min(20, Math.floor(downloadProgress.percentage / 5))
                ) }),
                /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u2591".repeat(
                  Math.max(
                    0,
                    20 - Math.floor(downloadProgress.percentage / 5)
                  )
                ) })
              ] })
            ] }) : /* @__PURE__ */ jsx(Text, { color: "gray", children: "Starting download..." })
          ]
        }
      );
    }
    if (step === "installed-options" && selectedInstalledModel) {
      const options = [
        { label: "Use this model", description: "Select this model for chat" },
        { label: "Delete model", description: "Remove from disk and uninstall" }
      ];
      return /* @__PURE__ */ jsxs(
        Box,
        {
          flexDirection: "column",
          borderStyle: "round",
          borderColor: "green",
          paddingX: 1,
          marginTop: 1,
          children: [
            /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
              /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: selectedInstalledModel.displayName }),
              /* @__PURE__ */ jsx(Text, { color: "gray", children: " (installed)" })
            ] }),
            isDeleting ? /* @__PURE__ */ jsx(Text, { color: "yellow", children: "Deleting model..." }) : /* @__PURE__ */ jsx(Fragment, { children: options.map((option, idx) => /* @__PURE__ */ jsxs(Box, { children: [
              /* @__PURE__ */ jsxs(Text, { color: idx === installedOptionIndex ? "cyan" : "white", children: [
                idx === installedOptionIndex ? "\u276F " : "  ",
                option.label
              ] }),
              idx === installedOptionIndex && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
                " - ",
                option.description
              ] })
            ] }, option.label)) }),
            error && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "red", children: error }) }),
            /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: isDeleting ? "Please wait..." : "Enter to select \u2022 Esc to go back" }) })
          ]
        }
      );
    }
    if (step === "custom-path") {
      return /* @__PURE__ */ jsxs(
        Box,
        {
          flexDirection: "column",
          borderStyle: "round",
          borderColor: "green",
          paddingX: 1,
          marginTop: 1,
          children: [
            /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "Custom GGUF File" }) }),
            /* @__PURE__ */ jsx(Text, { children: "Enter path to GGUF file:" }),
            /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
              /* @__PURE__ */ jsx(Text, { color: "gray", children: "> " }),
              /* @__PURE__ */ jsx(Text, { children: customPath }),
              /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u258C" })
            ] }),
            /* @__PURE__ */ jsx(Text, { color: "gray", children: "e.g., /path/to/model.gguf or ~/models/llama.gguf" }),
            error && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "red", children: error }) }),
            /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Enter to continue \u2022 Esc to go back" }) })
          ]
        }
      );
    }
    if (step === "display-name") {
      return /* @__PURE__ */ jsxs(
        Box,
        {
          flexDirection: "column",
          borderStyle: "round",
          borderColor: "green",
          paddingX: 1,
          marginTop: 1,
          children: [
            /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "Display Name" }) }),
            /* @__PURE__ */ jsx(Text, { children: "Display name (optional):" }),
            /* @__PURE__ */ jsxs(Box, { marginTop: 1, children: [
              /* @__PURE__ */ jsx(Text, { color: "gray", children: "> " }),
              /* @__PURE__ */ jsx(Text, { children: displayName }),
              /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u258C" })
            ] }),
            error && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "red", children: error }) }),
            /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Enter to save \u2022 Esc to go back" }) })
          ]
        }
      );
    }
    const allItems = [
      ...models,
      { type: "show-all" },
      { type: "custom-path" },
      { type: "back" }
    ];
    const visibleStart = scrollOffset;
    const visibleEnd = Math.min(scrollOffset + MAX_VISIBLE_ITEMS, allItems.length);
    const visibleItems = allItems.slice(visibleStart, visibleEnd);
    return /* @__PURE__ */ jsxs(
      Box,
      {
        flexDirection: "column",
        borderStyle: "round",
        borderColor: "green",
        paddingX: 1,
        marginTop: 1,
        children: [
          /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
            /* @__PURE__ */ jsx(Text, { bold: true, color: "green", children: "Local Model" }),
            /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
              " ",
              "(",
              selectedIndex + 1,
              "/",
              allItems.length,
              ")"
            ] })
          ] }),
          /* @__PURE__ */ jsx(
            SetupInfoBanner,
            {
              title: "Local Models",
              description: "Select a model to download, or use a custom GGUF file. Models run completely on your machine - free, private, and offline.",
              docsUrl: "https://docs.dexto.ai/docs/guides/supported-llm-providers#local-models"
            }
          ),
          visibleItems.map((item, visibleIndex) => {
            const actualIndex = scrollOffset + visibleIndex;
            const isSelected = actualIndex === selectedIndex;
            if ("type" in item) {
              if (item.type === "show-all") {
                return /* @__PURE__ */ jsxs(Box, { paddingY: 0, children: [
                  /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : "blue", bold: isSelected, children: [
                    isSelected ? "\u203A " : "  ",
                    showAllModels ? "\u21A9 Show recommended" : "... Show all models"
                  ] }),
                  /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
                    " ",
                    "(",
                    getAllLocalModels().length,
                    " available)"
                  ] })
                ] }, "show-all");
              }
              if (item.type === "custom-path") {
                return /* @__PURE__ */ jsx(Box, { paddingY: 0, children: /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : "blue", bold: isSelected, children: [
                  isSelected ? "\u203A " : "  ",
                  "... Use custom GGUF file"
                ] }) }, "custom-path");
              }
              if (item.type === "back") {
                return /* @__PURE__ */ jsx(Box, { paddingY: 0, children: /* @__PURE__ */ jsxs(Text, { color: isSelected ? "cyan" : "gray", bold: isSelected, children: [
                  isSelected ? "\u203A " : "  ",
                  "\u2190 Back"
                ] }) }, "back");
              }
            }
            const model = item;
            const statusIcon = model.isInstalled ? "\u2713" : "\u25CB";
            const statusColor = model.isInstalled ? "green" : "gray";
            const vramHint = model.minVRAM ? `${model.minVRAM}GB+ VRAM` : "CPU OK";
            return /* @__PURE__ */ jsxs(Box, { paddingY: 0, children: [
              /* @__PURE__ */ jsx(Text, { color: isSelected ? "cyan" : "white", bold: isSelected, children: isSelected ? "\u203A " : "  " }),
              /* @__PURE__ */ jsxs(Text, { color: statusColor, children: [
                statusIcon,
                " "
              ] }),
              /* @__PURE__ */ jsx(Text, { color: isSelected ? "cyan" : "white", bold: isSelected, children: model.name }),
              /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
                " ",
                formatSize(model.sizeBytes),
                " | ",
                vramHint,
                model.isInstalled ? " (installed)" : ""
              ] })
            ] }, model.id);
          }),
          allItems.length > MAX_VISIBLE_ITEMS && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
            scrollOffset > 0 ? "\u2191 more above " : "",
            visibleEnd < allItems.length ? "\u2193 more below" : ""
          ] }) }),
          /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u2191\u2193 navigate \u2022 Enter select \u2022 Esc back" }) }),
          error && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { color: "red", children: error }) })
        ]
      }
    );
  }
);
var LocalModelWizard_default = LocalModelWizard;
export {
  LocalModelWizard_default as default
};
