// src/components/Textarea.tsx
import React from "react";
import styled from "styled-components";

type Props = Omit<
  React.TextareaHTMLAttributes<HTMLTextAreaElement>,
  "placeholder"
> & {
  label: string;
  fullWidth?: boolean;
  errorText?: string;
  /** максимум строк для автосайза (по умолчанию 4) */
  maxRows?: number;
};

/* базовый textarea — в тех же цветах и шрифтах, что и Input */
const TextareaEl = styled.textarea`
  width: 100%;
  min-height: 56px;
  height: auto;
  border: 0;
  outline: none;
  border-radius: 8px;
  background: #f5f8fb;
  padding: 23px 16px 8px; /* сверху место под плавающий лейбл */
  color: #24303b;
  resize: none;          /* управляем высотой сами */
  overflow-y: hidden;    /* до достижения maxRows не показываем скролл */

  font-family: "GTAmerica", sans-serif;
  font-weight: 400;
  font-size: 18px;
  line-height: 24px;

  transition: box-shadow 0.18s ease, background 0.18s ease;

  /* нужен пустой placeholder, чтобы работал :placeholder-shown */
  &::placeholder {
    color: transparent;
  }

  &:focus {
    box-shadow: 0 0 0 2px rgba(22, 163, 74, 0.22);
  }
`;

const Label = styled.label`
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  transform-origin: left top;
  background:#f5f8fb;
  padding: 5px 0px;
  padding-right:10px;
  color: #1d2023;
  font-family: "GTAmerica", sans-serif;
  font-weight: 400;
  font-size: 18px;
  line-height: 24px;
  border-radius:5px;

  pointer-events: none;
  transition: top 0.18s ease, transform 0.18s ease, font-size 0.18s ease,
    line-height 0.18s ease;

  /* плавающий лейбл — при фокусе или когда поле не пустое */
  ${TextareaEl}:focus + &,
  ${TextareaEl}:not(:placeholder-shown) + & {
    top: 1px;
    transform: none;
    font-size: 12px;
    line-height: 16px;
  }
`;

const Field = styled.div<{ $full?: boolean; $error?: boolean }>`
  position: relative;
  width: ${({ $full }) => ($full ? "100%" : "auto")};

  ${({ $error }) =>
    $error
      ? `
      ${TextareaEl} { box-shadow: 0 0 0 2px rgba(220, 38, 38, .25); }
      ${Label}      { color: #dc2626; }
    `
      : ""}
`;

const ErrorText = styled.div`
  margin-top: 6px;
  color: #dc2626;
  font-family: "GTAmerica", sans-serif;
  font-size: 12px;
  line-height: 16px;
`;

function useMergedRefs<T>(
  ...refs: Array<React.Ref<T> | undefined>
): React.RefCallback<T> {
  return React.useCallback(
    (value: T) => {
      refs.forEach((ref) => {
        if (!ref) return;
        if (typeof ref === "function") ref(value);
        else (ref as React.MutableRefObject<T | null>).current = value;
      });
    },
    [refs]
  );
}

const Textarea = React.forwardRef<HTMLTextAreaElement, Props>(
  (
    {
      label,
      id,
      fullWidth,
      errorText,
      maxRows = 4,
      maxLength = 500,
      onChange,
      onInput,
      style,
      ...rest
    },
    ref
  ) => {
    const autoId = React.useId();
    const textareaId = id ?? autoId;
    const innerRef = React.useRef<HTMLTextAreaElement | null>(null);
    const mergedRef = useMergedRefs(ref, innerRef);

    const resize = React.useCallback(() => {
      const el = innerRef.current;
      if (!el) return;

      // предварительно сбрасываем высоту, чтобы корректно считать scrollHeight
      el.style.height = "auto";

      const cs = window.getComputedStyle(el);
      const lineHeight = parseFloat(cs.lineHeight || "24") || 24;
      const paddingTop = parseFloat(cs.paddingTop || "0");
      const paddingBottom = parseFloat(cs.paddingBottom || "0");
      const borderTop = parseFloat(cs.borderTopWidth || "0");
      const borderBottom = parseFloat(cs.borderBottomWidth || "0");

      const maxPx = lineHeight * maxRows + paddingTop + paddingBottom + borderTop + borderBottom;

      const next = Math.min(el.scrollHeight, Math.ceil(maxPx));
      el.style.height = `${next}px`;

      // если достигли предела — позволяем вертикальный скролл
      el.style.overflowY = el.scrollHeight > maxPx ? "auto" : "hidden";
    }, [maxRows]);

    React.useLayoutEffect(() => {
      resize();
    }, [resize]);

    const handleInput: React.FormEventHandler<HTMLTextAreaElement> = (e) => {
      resize();
      onInput?.(e);
    };

    const handleChange: React.ChangeEventHandler<HTMLTextAreaElement> = (e) => {
      // лишняя защита: обрезаем вручную, если вдруг превысили
      if (e.currentTarget.value.length > maxLength) {
        e.currentTarget.value = e.currentTarget.value.slice(0, maxLength);
      }
      onChange?.(e);
    };

    return (
      <Field $full={fullWidth} $error={!!errorText}>
        {/* placeholder=" " — чтобы работал :placeholder-shown */}
        <TextareaEl
          id={textareaId}
          ref={mergedRef}
          maxLength={maxLength}
          rows={1}
          placeholder=" "
          onInput={handleInput}
          onChange={handleChange}
          style={style}
          {...rest}
        />
        <Label htmlFor={textareaId}>{label}</Label>
        {errorText && <ErrorText>{errorText}</ErrorText>}
      </Field>
    );
  }
);

Textarea.displayName = "Textarea";
export default Textarea;
