import { jsx, jsxs } from "react/jsx-runtime";
import React, {
  useState,
  useEffect,
  useRef,
  useMemo,
  useCallback,
  forwardRef,
  useImperativeHandle
} from "react";
import { Box, Text } from "ink";
import path from "path";
import { centerTruncatePath } from "../utils/messageFormatting.js";
import { useTerminalSize } from "../hooks/useTerminalSize.js";
import { getMaxVisibleItemsForTerminalRows } from "../utils/overlaySizing.js";
import { supportsResources } from "../agent-backend.js";
function getResourceMatchScore(resource, query) {
  if (!query) return 3;
  const lowerQuery = query.toLowerCase();
  const name = (resource.name || "").toLowerCase();
  const uri = resource.uri.toLowerCase();
  const uriFilename = uri.split(/[\\/]/).pop()?.toLowerCase() || "";
  const description = (resource.description || "").toLowerCase();
  if (name.startsWith(lowerQuery)) {
    return 4;
  }
  if (name.includes(lowerQuery)) {
    return 3;
  }
  if (uriFilename.startsWith(lowerQuery)) {
    return 2;
  }
  if (uriFilename.includes(lowerQuery)) {
    return 2;
  }
  if (uri.includes(lowerQuery)) {
    return 1;
  }
  if (description.includes(lowerQuery)) {
    return 1;
  }
  return 0;
}
function matchesQuery(resource, query) {
  return getResourceMatchScore(resource, query) > 0;
}
function sortResources(resources, query) {
  if (!query) return resources;
  const lowerQuery = query.toLowerCase();
  return [...resources].sort((a, b) => {
    const scoreA = getResourceMatchScore(a, lowerQuery);
    const scoreB = getResourceMatchScore(b, lowerQuery);
    if (scoreA !== scoreB) {
      return scoreB - scoreA;
    }
    const aName = (a.name || "").toLowerCase();
    const bName = (b.name || "").toLowerCase();
    return aName.localeCompare(bName);
  });
}
const ResourceAutocompleteInner = forwardRef(
  function ResourceAutocomplete({ isVisible, searchQuery, onSelectResource, onLoadIntoInput, onClose, agent }, ref) {
    const [resources, setResources] = useState([]);
    const [isLoading, setIsLoading] = useState(false);
    const { columns: terminalWidth, rows: terminalRows } = useTerminalSize();
    const maxVisibleItems = useMemo(() => {
      return getMaxVisibleItemsForTerminalRows({
        rows: terminalRows,
        hardCap: 15,
        reservedRows: 6
      });
    }, [terminalRows]);
    const [selection, setSelection] = useState({ index: 0, offset: 0 });
    const selectedIndexRef = useRef(0);
    const updateSelection = useCallback(
      (indexUpdater) => {
        setSelection((prev) => {
          const newIndex = typeof indexUpdater === "function" ? indexUpdater(prev.index) : indexUpdater;
          selectedIndexRef.current = newIndex;
          let newOffset = prev.offset;
          if (newIndex < prev.offset) {
            newOffset = newIndex;
          } else if (newIndex >= prev.offset + maxVisibleItems) {
            newOffset = Math.max(0, newIndex - maxVisibleItems + 1);
          }
          return { index: newIndex, offset: newOffset };
        });
      },
      [maxVisibleItems]
    );
    useEffect(() => {
      if (!isVisible) return;
      let cancelled = false;
      setIsLoading(true);
      const fetchResources = async () => {
        try {
          if (!supportsResources(agent)) {
            if (!cancelled) {
              setResources([]);
              setIsLoading(false);
            }
            return;
          }
          const resourceSet = await agent.listResources();
          const resourceList = Object.values(resourceSet);
          if (!cancelled) {
            setResources(resourceList);
            setIsLoading(false);
          }
        } catch {
          if (!cancelled) {
            setResources([]);
            setIsLoading(false);
          }
        }
      };
      void fetchResources();
      return () => {
        cancelled = true;
      };
    }, [isVisible, agent]);
    const mentionQuery = useMemo(() => {
      const atIndex = searchQuery.lastIndexOf("@");
      if (atIndex === -1) return "";
      const prevChar = searchQuery[atIndex - 1];
      if (atIndex === 0 || prevChar && /\s/.test(prevChar)) {
        return searchQuery.slice(atIndex + 1).trim();
      }
      return "";
    }, [searchQuery]);
    const displayItems = useMemo(() => {
      const items = [];
      const directories = /* @__PURE__ */ new Set();
      resources.forEach((resource) => {
        let relativePath = resource.uri;
        const rawUri = relativePath.replace(/^(fs|file):\/\//, "");
        if (path.isAbsolute(rawUri)) {
          try {
            const relPath = path.relative(process.cwd(), rawUri);
            if (relPath && !relPath.startsWith("..")) {
              relativePath = relPath;
            } else {
              const uriParts = resource.uri.split(/[\\/]/);
              relativePath = resource.name || uriParts[uriParts.length - 1] || resource.uri;
            }
          } catch {
            return;
          }
        }
        items.push({
          path: relativePath,
          isDirectory: false,
          resource
        });
        const segments = relativePath.split(path.sep).filter(Boolean);
        for (let i = 0; i < Math.min(segments.length - 1, 2); i++) {
          const dirPath = segments.slice(0, i + 1).join(path.sep) + path.sep;
          directories.add(dirPath);
        }
      });
      directories.forEach((dirPath) => {
        items.push({
          path: dirPath,
          isDirectory: true
        });
      });
      const filtered = items.filter((item) => {
        if (!mentionQuery) return true;
        const lowerQuery = mentionQuery.toLowerCase();
        const lowerPath = item.path.toLowerCase();
        const pathParts = item.path.split(path.sep).filter(Boolean);
        const lastSegment = pathParts[pathParts.length - 1]?.toLowerCase() || "";
        if (lastSegment.includes(lowerQuery) || lowerPath.includes(lowerQuery)) {
          return true;
        }
        if (item.resource) {
          const lowerName = (item.resource.name || "").toLowerCase();
          const lowerDescription = (item.resource.description || "").toLowerCase();
          if (lowerName.includes(lowerQuery) || lowerDescription.includes(lowerQuery)) {
            return true;
          }
        }
        return false;
      });
      return filtered.sort((a, b) => {
        if (!mentionQuery) {
          if (a.isDirectory !== b.isDirectory) {
            return a.isDirectory ? -1 : 1;
          }
          return a.path.localeCompare(b.path);
        }
        const lowerQuery = mentionQuery.toLowerCase();
        const aPathParts = a.path.split(path.sep).filter(Boolean);
        const bPathParts = b.path.split(path.sep).filter(Boolean);
        const aLastSegment = aPathParts[aPathParts.length - 1]?.toLowerCase() || "";
        const bLastSegment = bPathParts[bPathParts.length - 1]?.toLowerCase() || "";
        const aStartsWith = aLastSegment.startsWith(lowerQuery);
        const bStartsWith = bLastSegment.startsWith(lowerQuery);
        const aIncludes = aLastSegment.includes(lowerQuery);
        const bIncludes = bLastSegment.includes(lowerQuery);
        if (aStartsWith && !bStartsWith) return -1;
        if (!aStartsWith && bStartsWith) return 1;
        if (aIncludes && !bIncludes) return -1;
        if (!aIncludes && bIncludes) return 1;
        const depthDiff = aPathParts.length - bPathParts.length;
        if (depthDiff !== 0) return depthDiff;
        return a.path.localeCompare(b.path);
      });
    }, [resources, mentionQuery]);
    const prevItemsLengthRef = useRef(displayItems.length);
    const itemsChanged = displayItems.length !== prevItemsLengthRef.current;
    const selectedIndex = itemsChanged ? 0 : Math.min(selection.index, Math.max(0, displayItems.length - 1));
    const scrollOffset = itemsChanged ? 0 : Math.min(selection.offset, Math.max(0, displayItems.length - maxVisibleItems));
    useEffect(() => {
      if (itemsChanged) {
        prevItemsLengthRef.current = displayItems.length;
        if (selection.index !== 0 || selection.offset !== 0) {
          selectedIndexRef.current = 0;
          setSelection({ index: 0, offset: 0 });
        } else {
          selectedIndexRef.current = 0;
        }
      }
    }, [itemsChanged, displayItems.length, selection.index, selection.offset]);
    const visibleResources = useMemo(() => {
      return displayItems.slice(scrollOffset, scrollOffset + maxVisibleItems);
    }, [displayItems, scrollOffset, maxVisibleItems]);
    useImperativeHandle(
      ref,
      () => ({
        handleInput: (_input, key) => {
          if (!isVisible) return false;
          if (key.escape) {
            onClose();
            return true;
          }
          const itemsLength = displayItems.length;
          if (itemsLength === 0) return false;
          if (key.upArrow) {
            updateSelection((prev) => (prev - 1 + itemsLength) % itemsLength);
            return true;
          }
          if (key.downArrow) {
            updateSelection((prev) => (prev + 1) % itemsLength);
            return true;
          }
          if (key.tab) {
            const item = displayItems[selectedIndexRef.current];
            if (!item) return false;
            const atIndex = searchQuery.lastIndexOf("@");
            const reference = item.path;
            if (atIndex >= 0) {
              const before = searchQuery.slice(0, atIndex + 1);
              onLoadIntoInput?.(`${before}${reference}`);
            } else {
              onLoadIntoInput?.(`${searchQuery}@${reference}`);
            }
            return true;
          }
          if (key.return) {
            const item = displayItems[selectedIndexRef.current];
            if (!item) return false;
            if (item.isDirectory) {
              const atIndex = searchQuery.lastIndexOf("@");
              if (atIndex >= 0) {
                const before = searchQuery.slice(0, atIndex + 1);
                onLoadIntoInput?.(`${before}${item.path}`);
              } else {
                onLoadIntoInput?.(`${searchQuery}@${item.path}`);
              }
            } else if (item.resource) {
              onSelectResource(item.resource);
            }
            return true;
          }
          return false;
        }
      }),
      [
        isVisible,
        displayItems,
        selectedIndexRef,
        searchQuery,
        onClose,
        onLoadIntoInput,
        onSelectResource,
        updateSelection
      ]
    );
    if (!isVisible) return null;
    if (isLoading) {
      return /* @__PURE__ */ jsx(Box, { paddingX: 0, paddingY: 0, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: "Loading resources..." }) });
    }
    if (displayItems.length === 0) {
      return /* @__PURE__ */ jsx(Box, { paddingX: 0, paddingY: 0, children: /* @__PURE__ */ jsx(Text, { color: "gray", children: mentionQuery ? `No resources match "${mentionQuery}"` : "No resources available. Connect an MCP server or enable internal resources." }) });
    }
    return /* @__PURE__ */ jsx(Box, { flexDirection: "column", width: terminalWidth, paddingLeft: 2, children: visibleResources.map((item, visibleIndex) => {
      const actualIndex = scrollOffset + visibleIndex;
      const isSelected = actualIndex === selectedIndex;
      const displayPath = centerTruncatePath(
        item.path,
        Math.max(20, terminalWidth - 16)
      );
      const isImage = item.resource?.mimeType?.startsWith("image/");
      return /* @__PURE__ */ jsxs(Box, { children: [
        /* @__PURE__ */ jsx(Text, { color: isSelected ? "cyan" : "gray", children: isSelected ? "\u276F " : "  " }),
        /* @__PURE__ */ jsxs(
          Text,
          {
            wrap: "truncate-end",
            color: isSelected ? "cyan" : "white",
            bold: isSelected,
            children: [
              isImage && "\u{1F5BC}\uFE0F  ",
              displayPath,
              item.resource?.serverName && ` [${item.resource.serverName}]`
            ]
          }
        )
      ] }, item.path);
    }) });
  }
);
const ResourceAutocomplete2 = React.memo(
  ResourceAutocompleteInner
);
var ResourceAutocomplete_default = ResourceAutocomplete2;
export {
  ResourceAutocomplete_default as default
};
