import { jsx, jsxs } from "react/jsx-runtime";
import { forwardRef, useState, useRef, useCallback } from "react";
import { Box } from "../Box/Box.mjs";
import parseHighlights from "autosuggest-highlight/parse/index.js";
import { Highlight } from "./Highlight/Highlight.mjs";
import { Field } from "../private/Field/Field.mjs";
import { Text } from "../Accordion/AccordionItem.mjs";
import { highlights, field } from "./Textarea.css.mjs";
const formatRanges = (value, highlightRanges, tone) => {
  if (highlightRanges && value) {
    let lastEnd = 0;
    const validatedAndSortedRanges = highlightRanges.sort((a, b) => a.start > b.start ? 1 : -1).reduce((acc, { end, start }) => {
      const resolvedEnd = end || value.length;
      if (resolvedEnd <= start) {
        return acc;
      }
      const adjustedRange = [];
      if (resolvedEnd > lastEnd) {
        adjustedRange.push({
          // if overlapping, start from end of last range otherwise start from specified range
          start: start < lastEnd ? lastEnd : start,
          end
        });
        lastEnd = resolvedEnd;
      }
      return [...acc, ...adjustedRange];
    }, []);
    return parseHighlights(
      value,
      validatedAndSortedRanges.map(({ start, end }) => [
        start,
        end || value.length
      ])
    ).reduce((acc, { text, highlight }, i) => {
      if (text) {
        acc.push(
          highlight ? /* @__PURE__ */ jsx(Highlight, { tone, children: text }, i) : text
        );
      }
      return acc;
    }, []);
  }
  return [value];
};
const getCharacterLimitStatus = ({
  characterLimit,
  value
}) => {
  const inputLength = String(value).length;
  if (inputLength < Math.ceil(characterLimit * 0.7 / 10) * 10) {
    return null;
  }
  const diff = characterLimit - inputLength;
  const valid = diff >= 0;
  return /* @__PURE__ */ jsx(Text, { size: "small", tone: valid ? "secondary" : "critical", children: diff });
};
const pxToInt = (str) => typeof str === "string" ? parseInt(str.replace("px", ""), 10) : 0;
const calculateLines = (target, lines, lineLimit) => {
  const { paddingBottom, paddingTop, lineHeight } = window.getComputedStyle(target);
  if (!lineHeight.endsWith("px")) {
    return lines;
  }
  const padding = pxToInt(paddingTop) + pxToInt(paddingBottom);
  const currentRows = Math.floor(
    (target.scrollHeight - padding) / pxToInt(lineHeight)
  );
  if (target && target.value === "") {
    return lines;
  }
  return typeof lineLimit === "number" && currentRows > lineLimit ? lineLimit : currentRows;
};
const Textarea = forwardRef(
  ({
    value,
    onChange,
    onBlur,
    onFocus,
    onPaste,
    placeholder,
    characterLimit,
    highlightRanges: highlightRangesProp = [],
    lines = 3,
    lineLimit,
    grow = true,
    tone,
    spellCheck,
    ...restProps
  }, ref) => {
    const [rows, setRows] = useState(lines);
    const highlightsRef = useRef(null);
    const updateScroll = useCallback(
      (scrollTop) => {
        if (highlightsRef.current) {
          highlightsRef.current.scrollTop = scrollTop;
        }
      },
      [highlightsRef]
    );
    const inputLength = String(value).length;
    const hasExceededCharacterLimit = characterLimit && inputLength > characterLimit;
    const highlightTone = !hasExceededCharacterLimit && (tone === "critical" || tone === "caution") ? tone : "critical";
    const highlightRanges = hasExceededCharacterLimit ? [{ start: characterLimit }] : highlightRangesProp;
    const hasHighlights = highlightRanges.length > 0;
    return /* @__PURE__ */ jsx(
      Field,
      {
        ...restProps,
        tone,
        value,
        icon: void 0,
        prefix: void 0,
        secondaryMessage: characterLimit ? getCharacterLimitStatus({
          value,
          characterLimit
        }) : null,
        children: (overlays, { className, borderRadius, background, ...fieldProps }) => /* @__PURE__ */ jsxs(
          Box,
          {
            position: "relative",
            width: "full",
            zIndex: 0,
            background,
            borderRadius,
            children: [
              hasHighlights ? /* @__PURE__ */ jsx(
                Box,
                {
                  ref: highlightsRef,
                  position: "absolute",
                  overflow: "hidden",
                  pointerEvents: "none",
                  height: "full",
                  "aria-hidden": "true",
                  top: 0,
                  left: 0,
                  className: [highlights, className],
                  ...fieldProps,
                  children: formatRanges(String(value), highlightRanges, highlightTone)
                }
              ) : null,
              /* @__PURE__ */ jsx(
                Box,
                {
                  component: "textarea",
                  position: "relative",
                  zIndex: 1,
                  rows,
                  value,
                  onChange: (e) => {
                    if (grow) {
                      setRows(calculateLines(e.currentTarget, lines, lineLimit));
                    }
                    if (typeof onChange === "function") {
                      onChange(e);
                    }
                    if (hasHighlights) {
                      updateScroll(e.currentTarget.scrollTop);
                    }
                  },
                  onBlur,
                  onFocus,
                  onPaste,
                  onScroll: hasHighlights ? (event) => updateScroll(event.currentTarget.scrollTop) : void 0,
                  placeholder: !restProps.disabled ? placeholder : void 0,
                  spellCheck,
                  className: [field, className],
                  ...fieldProps,
                  ref
                }
              ),
              overlays
            ]
          }
        )
      }
    );
  }
);
Textarea.displayName = "Textarea";
export {
  Textarea,
  getCharacterLimitStatus
};
