"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var ConnectOverlay_exports = {};
__export(ConnectOverlay_exports, {
  default: () => ConnectOverlay_default
});
module.exports = __toCommonJS(ConnectOverlay_exports);
var import_jsx_runtime = require("react/jsx-runtime");
var import_react = require("react");
var import_ink = require("ink");
var import_open = __toESM(require("open"), 1);
var import_BaseSelector = require("../base/BaseSelector.js");
var import_agent_management = require("@dexto/agent-management");
var import_llm = require("@dexto/llm");
var import_host = require("../../host/index.js");
function methodHint(method, profile, defaultProfileId) {
  const parts = [
    profile ? profile.id === defaultProfileId ? "Connected (default)" : "Connected" : void 0,
    method.hint
  ].filter((part) => Boolean(part));
  return parts.length ? parts.join(" - ") : void 0;
}
function maskSecret(secret) {
  if (secret.length <= 8) {
    return "*".repeat(secret.length);
  }
  return `${secret.slice(0, 4)}${"*".repeat(Math.min(secret.length - 8, 24))}${secret.slice(-4)}`;
}
function toLlmProvider(providerId) {
  const provider = import_llm.LLM_PROVIDERS.find((candidate) => candidate === providerId);
  if (!provider) {
    throw new Error(`API-key auth is not implemented for provider: ${providerId}`);
  }
  return provider;
}
const ConnectOverlay = (0, import_react.forwardRef)(
  function ConnectOverlay2({ isVisible, onDone }, ref) {
    const selectorRef = (0, import_react.useRef)(null);
    const loginCancelRef = (0, import_react.useRef)(null);
    const [step, setStep] = (0, import_react.useState)("provider");
    const [selectedIndex, setSelectedIndex] = (0, import_react.useState)(0);
    const [provider, setProvider] = (0, import_react.useState)(null);
    const [method, setMethod] = (0, import_react.useState)(null);
    const [profiles, setProfiles] = (0, import_react.useState)([]);
    const [defaultProfileId, setDefaultProfileId] = (0, import_react.useState)(null);
    const [apiKey, setApiKey] = (0, import_react.useState)("");
    const [status, setStatus] = (0, import_react.useState)("Choose a provider to connect.");
    const [error, setError] = (0, import_react.useState)(null);
    const currentProfileId = provider && method ? (0, import_agent_management.getModelAuthProfileId)(provider.providerId, method.id) : null;
    const existingProfile = currentProfileId ? profiles.find((profile) => profile.id === currentProfileId) ?? null : null;
    const close = (0, import_react.useCallback)(
      (outcome) => {
        void loginCancelRef.current?.();
        loginCancelRef.current = null;
        onDone(outcome);
      },
      [onDone]
    );
    const handleActionError = (0, import_react.useCallback)((err) => {
      setError(err instanceof Error ? err.message : String(err));
      setStep("error");
    }, []);
    (0, import_react.useEffect)(() => {
      if (!isVisible) {
        return;
      }
      setStep("provider");
      setSelectedIndex(0);
      setProvider(null);
      setMethod(null);
      setProfiles([]);
      setDefaultProfileId(null);
      setApiKey("");
      setStatus("Choose a provider to connect.");
      setError(null);
    }, [isVisible]);
    const providerOptions = (0, import_react.useMemo)(
      () => (0, import_agent_management.getProviderAuthDefinitions)().map((item) => ({
        value: item.providerId,
        label: item.label,
        hint: `${item.methods.length} method${item.methods.length === 1 ? "" : "s"}`
      })),
      []
    );
    const methodOptions = (0, import_react.useMemo)(() => {
      if (!provider) {
        return [];
      }
      return provider.methods.map((item) => {
        const profile = profiles.find(
          (candidate) => candidate.id === (0, import_agent_management.getModelAuthProfileId)(provider.providerId, item.id)
        );
        return {
          value: item.id,
          label: item.label,
          hint: methodHint(item, profile, defaultProfileId)
        };
      });
    }, [defaultProfileId, profiles, provider]);
    const existingActionOptions = (0, import_react.useMemo)(() => {
      if (!existingProfile) {
        return [];
      }
      return [
        {
          value: "use",
          label: existingProfile.id === defaultProfileId ? "Keep as default" : "Use existing",
          hint: existingProfile.id === defaultProfileId ? "No changes" : "Set this method as provider default"
        },
        { value: "replace", label: "Replace credentials", hint: "Reconnect this method" },
        {
          value: "delete",
          label: "Delete credentials",
          ...existingProfile.id === defaultProfileId ? { hint: "Also clears default" } : {}
        }
      ];
    }, [defaultProfileId, existingProfile]);
    const activeItems = step === "provider" ? providerOptions : step === "method" ? methodOptions : step === "existing-action" ? existingActionOptions : [];
    const loadProvider = (0, import_react.useCallback)(async (nextProvider) => {
      setProvider(nextProvider);
      setMethod(null);
      setStatus(`Loading saved ${nextProvider.label} profiles...`);
      const [savedProfiles, savedDefaultProfileId] = await Promise.all([
        (0, import_agent_management.listSavedModelAuthProfiles)(nextProvider.providerId),
        (0, import_agent_management.getDefaultModelAuthProfileIdForProvider)(nextProvider.providerId)
      ]);
      setProfiles(savedProfiles);
      setDefaultProfileId(savedDefaultProfileId);
      setSelectedIndex(0);
      setStatus(`Choose how to connect ${nextProvider.label}.`);
      setStep("method");
    }, []);
    const saveApiKey = (0, import_react.useCallback)(async () => {
      if (!provider || !method) {
        close({ outcome: "cancelled" });
        return;
      }
      const trimmed = apiKey.trim();
      if (!trimmed) {
        setError("API key is required");
        return;
      }
      const llmProvider = toLlmProvider(provider.providerId);
      if (!(0, import_host.isValidApiKeyFormat)(trimmed, llmProvider)) {
        setError(`${provider.label} API key format is invalid`);
        return;
      }
      setError(null);
      try {
        setStatus(`Saving ${provider.label} API key...`);
        await (0, import_agent_management.saveProviderApiKey)(llmProvider, trimmed, process.cwd());
        await (0, import_host.applyLayeredEnvironmentLoading)();
        await (0, import_agent_management.saveApiKeyModelAuthProfile)(llmProvider);
        await (0, import_agent_management.markModelAuthProviderConnected)(provider.providerId);
        close({
          outcome: "success",
          providerId: provider.providerId,
          message: `Connected ${provider.label} (${method.label})`
        });
      } catch (err) {
        setError(err instanceof Error ? err.message : String(err));
      }
    }, [apiKey, close, method, provider]);
    const connectOAuth = (0, import_react.useCallback)(
      async (nextProvider, nextMethod) => {
        setStep("oauth-progress");
        setStatus(`Starting ${nextMethod.label}...`);
        let timeout = null;
        try {
          const login = await (0, import_agent_management.startModelAuthBrowserLogin)({
            providerId: nextProvider.providerId,
            methodId: nextMethod.id
          });
          loginCancelRef.current = login.cancel;
          setStatus(`Opening browser for ${nextMethod.label}...`);
          await (0, import_open.default)(login.authUrl).catch(() => void 0);
          setStatus("Waiting for browser authorization...");
          await Promise.race([
            login.waitForProfile(),
            new Promise((_, reject) => {
              timeout = setTimeout(
                () => reject(new Error(`${nextMethod.label} timed out`)),
                5 * 60 * 1e3
              );
            })
          ]);
          await (0, import_agent_management.markModelAuthProviderConnected)(nextProvider.providerId);
          close({
            outcome: "success",
            providerId: nextProvider.providerId,
            message: `Connected ${nextProvider.label} (${nextMethod.label})`
          });
        } catch (err) {
          setError(err instanceof Error ? err.message : String(err));
          setStep("error");
        } finally {
          if (timeout) {
            clearTimeout(timeout);
          }
          await loginCancelRef.current?.();
          loginCancelRef.current = null;
        }
      },
      [close]
    );
    const startConnect = (0, import_react.useCallback)(async () => {
      if (!provider || !method) {
        close({ outcome: "cancelled" });
        return;
      }
      if (method.kind === "api_key") {
        setApiKey("");
        setError(null);
        setStatus(`Enter your ${provider.label} API key.`);
        setStep("api-key");
        return;
      }
      if (method.kind === "oauth") {
        await connectOAuth(provider, method);
      }
    }, [close, connectOAuth, method, provider]);
    const handleSelect = (0, import_react.useCallback)(
      async (option) => {
        if (step === "provider") {
          const nextProvider = (0, import_agent_management.getProviderAuthDefinitions)().find(
            (candidate) => candidate.providerId === option.value
          );
          if (nextProvider) {
            await loadProvider(nextProvider);
          }
          return;
        }
        if (step === "method" && provider) {
          const nextMethod = provider.methods.find(
            (candidate) => candidate.id === option.value
          );
          if (nextMethod) {
            setMethod(nextMethod);
            const profileId = (0, import_agent_management.getModelAuthProfileId)(provider.providerId, nextMethod.id);
            if (profiles.some((item) => item.id === profileId)) {
              setStatus(`Manage ${provider.label} ${nextMethod.label}.`);
              setStep("existing-action");
              setSelectedIndex(0);
              return;
            }
            if (nextMethod.kind === "api_key") {
              setApiKey("");
              setError(null);
              setStatus(`Enter your ${provider.label} API key.`);
              setStep("api-key");
              return;
            }
            if (nextMethod.kind === "oauth") {
              await connectOAuth(provider, nextMethod);
            }
          }
          return;
        }
        if (step === "existing-action" && provider && method && currentProfileId) {
          if (option.value === "use") {
            await (0, import_agent_management.setDefaultModelAuthProfile)({
              providerId: provider.providerId,
              profileId: currentProfileId
            });
            close({
              outcome: "success",
              providerId: provider.providerId,
              message: `Using ${provider.label} ${method.label}`
            });
            return;
          }
          if (option.value === "replace") {
            await startConnect();
            return;
          }
          if (option.value === "delete") {
            setStatus(`Press Enter to delete ${provider.label} ${method.label}.`);
            setStep("delete-confirm");
          }
        }
      },
      [
        close,
        connectOAuth,
        currentProfileId,
        loadProvider,
        method,
        profiles,
        provider,
        startConnect,
        step
      ]
    );
    (0, import_react.useImperativeHandle)(
      ref,
      () => ({
        handleInput: (input, key) => {
          if (!isVisible) return false;
          if (step === "api-key") {
            if (key.escape) {
              close({ outcome: "cancelled" });
              return true;
            }
            if (key.return) {
              void saveApiKey().catch(handleActionError);
              return true;
            }
            if (key.backspace || key.delete) {
              setApiKey((prev) => prev.slice(0, -1));
              setError(null);
              return true;
            }
            if (input && !key.ctrl && !key.meta) {
              setApiKey((prev) => prev + input);
              setError(null);
              return true;
            }
            return true;
          }
          if (step === "delete-confirm") {
            if (key.escape) {
              close({ outcome: "cancelled" });
              return true;
            }
            if (key.return && provider && method && currentProfileId) {
              void (0, import_agent_management.deleteModelAuthProfile)(currentProfileId).then(
                () => close({
                  outcome: "success",
                  providerId: provider.providerId,
                  message: `Deleted ${provider.label} ${method.label}`
                })
              ).catch(handleActionError);
              return true;
            }
            return true;
          }
          if (step === "oauth-progress") {
            if (key.escape) {
              close({ outcome: "cancelled" });
            }
            return true;
          }
          if (step === "error") {
            if (key.escape || key.return) {
              close({ outcome: "closed" });
            }
            return true;
          }
          return selectorRef.current?.handleInput(input, key) ?? false;
        }
      }),
      [
        close,
        currentProfileId,
        handleActionError,
        isVisible,
        method,
        provider,
        saveApiKey,
        step
      ]
    );
    if (!isVisible) return null;
    return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { bold: true, color: "cyan", children: "Connect Model Provider" }) }),
      /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: error ? "red" : "gray", children: error ?? status }),
      step === "api-key" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", marginTop: 1, children: [
        /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: maskSecret(apiKey) }),
        /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Enter save \u2022 Esc cancel" })
      ] }) : step === "delete-confirm" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", marginTop: 1, children: [
        /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "red", children: "This removes saved credentials for this method." }),
        /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Enter delete \u2022 Esc cancel" })
      ] }) : step === "oauth-progress" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Esc cancel" }) }) : step === "error" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Enter close \u2022 Esc close" }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
        import_BaseSelector.BaseSelector,
        {
          ref: selectorRef,
          items: activeItems,
          isVisible: true,
          selectedIndex,
          onSelectIndex: setSelectedIndex,
          onSelect: (item) => void handleSelect(item).catch(handleActionError),
          onClose: () => close({ outcome: "cancelled" }),
          title: step === "provider" ? "Providers" : step === "method" ? `${provider?.label ?? "Provider"} methods` : "Existing profile",
          formatItem: (item, selected) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { ...selected ? { color: "cyan" } : {}, children: [
            selected ? "\u203A " : "  ",
            item.label,
            item.hint ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "gray", children: [
              " \u2014 ",
              item.hint
            ] }) : null
          ] })
        }
      ) })
    ] });
  }
);
var ConnectOverlay_default = ConnectOverlay;
