/**
 * Input — 单行文本输入（用户自造字符串）
 *
 * **何时用**：名称、搜索词、备注等不可穷举或需键盘录入的值。
 * **不用**：合法值仅来自固定列表 → `Select` 或 `Radio`；纯数字与步进 → `InputNumber`。
 *
 * @prop {'default'|'error'} [status='default'] — 状态
 * @prop {boolean} [disabled=false] — 是否禁用
 * @prop {import('react').ReactNode} [prefix=null] — 前缀
 * @prop {import('react').ReactNode} [suffix=null] — 后缀
 * @prop {boolean} [allowClear=false] — 可清除
 * @prop {string} [aiSuggestion] — 输入框下方单条 AI 推荐文案
 * @prop {string[]} [aiSuggestions] — 输入框下方多条 AI 推荐文案
 * @prop {string} [placeholder='请输入'] — 占位
 * @prop {string} value — 当前值（受控）
 * @prop {string} [defaultValue] — 非受控初值
 * @prop {(e: import('react').ChangeEvent<HTMLInputElement>) => void} [onChange] — 变更回调
 * @prop {() => void} [onClear] — 清除回调
 * @prop {(suggestion: string) => void} [onAdoptSuggestion] — 采纳 AI 推荐回调
 * @prop {() => void} [onRefreshAiSuggestions] — 刷新 AI 推荐回调
 * @prop {boolean} [aiSuggestionsLoading=false] — AI 推荐区加载中：展示 AI 渐变骨架面板（骨条填充 --gradient-ai-fill-1）
 * @prop {number} [aiSuggestionsLoadingCount=1] — 加载骨架推荐条数（1–5）
 * @prop {string} [className=''] — 类名
 * @prop {import('react').CSSProperties} [style] — 根容器样式，常用于设置 `--size-input-width`
 */
import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
import AiSuggestionPanel, { AiRefreshButton, buildSuggestionGroupsFromFlatList } from './AiSuggestionShared';
import { AiSuggestionPanelSkeleton } from './Skeleton';

/* ── 根容器基础样式 ── */
const WRAPPER_BASE = [
  'inline-flex flex-col items-start w-[var(--size-input-width,100%)] max-w-full gap-1',
  '[font-family:inherit]',
].join(' ');

/* ── 输入框基础样式 ── */
const FIELD_BASE = [
  'tfds-input',
  'group relative inline-flex items-center w-full',
  'border [border-style:solid] rounded-md',
  'transition-colors tfds-motion-ui-fast',
  'outline-none',
  '[font-family:inherit]',
].join(' ');

/* ── 状态 → 容器背景 / 边框（聚焦仅 1px 描边，聚焦优先级高于悬浮） ── */
const STATUS_CLASS = {
  default: [
    'bg-surface border-border-default',
    'hover:border-border-strong',
    'focus-within:border-primary',
    'focus-within:hover:border-primary',
  ].join(' '),
  error: [
    'bg-red-50 border-border-default',
    'hover:bg-red-100',
    'focus-within:border-red-500',
    'focus-within:hover:border-red-500 focus-within:hover:bg-red-50',
  ].join(' '),
};

/* ── 固定 MD 尺寸 → 高度 / 内边距 / 字号 / 间距 ── */
const SIZE_CLASS = 'h-[var(--size-control-md)] pl-3 pr-3 text-sm gap-2';

/* ── 禁用态（覆盖 status 的颜色，保留当前边框） ── */
const DISABLED_CLASS = 'bg-disabled border-border-default cursor-not-allowed opacity-60';

/* ── 原生 input 样式（透明无边框，继承容器字号；聚焦时 placeholder 更淡） ── */
const INPUT_BASE = [
  'flex-1 min-w-0 bg-transparent border-none outline-none',
  'text-foreground placeholder:text-foreground-muted',
  'focus:placeholder:text-foreground-disabled',
  '[font-family:inherit] [font-size:inherit] leading-[var(--leading-5)]',
  'disabled:text-foreground-disabled disabled:placeholder:text-foreground-disabled',
  'p-0 m-0',
].join(' ');

/* ── 前后缀插槽 ── */
const ADDON_CLASS = 'inline-flex size-[16px] items-center justify-center shrink-0 text-foreground-muted [&>svg]:size-[16px]';

/* ── 清除按钮（hover 或聚焦时出现） ── */
const CLEAR_CLASS = [
  'inline-flex items-center justify-center shrink-0 size-[var(--spacing-4)]',
  'rounded-full cursor-pointer',
  'text-foreground-disabled hover:text-foreground-secondary',
  'opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 transition-opacity tfds-motion-ui-fast',
  'bg-transparent border-none p-0',
].join(' ');

const TRAILING_CLASS = 'absolute right-3 top-1/2 inline-flex -translate-y-1/2 items-center gap-2';

const INPUT_LOCAL_FALLBACK_SUGGESTION_GROUPS = [
  ['您好，这边已经收到您的反馈，正在为您核实处理。'],
  ['您好，问题已记录，这边会尽快同步处理进展。'],
];

function dispatchNativeInputValue(input, nextValue) {
  if (!input) return;
  const descriptor = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value');
  descriptor?.set?.call(input, nextValue);
  input.dispatchEvent(new Event('input', { bubbles: true }));
}

function getInputPaddingClasses(hasSuffix, activeButtonCount) {
  const base = hasSuffix ? 'pr-7' : '';
  if (activeButtonCount === 0) return base;

  if (activeButtonCount === 1) {
    return `${base} group-hover:pr-8 group-focus-within:pr-8`.trim();
  }
  return `${base} group-hover:pr-14 group-focus-within:pr-14`.trim();
}

export default function Input({
  size: _size = 'md',
  status = 'default',
  disabled = false,
  prefix,
  suffix,
  allowClear = false,
  aiSuggestion,
  aiSuggestions,
  placeholder = '请输入',
  value,
  defaultValue,
  onChange,
  onClear,
  onAdoptSuggestion,
  onRefreshAiSuggestions,
  aiSuggestionsLoading = false,
  aiSuggestionsLoadingCount = 1,
  className = '',
  style,
  ...rest
}) {
  const inputRef = useRef(null);
  const isControlled = value !== undefined;
  const [innerValue, setInnerValue] = useState(defaultValue || '');
  const [isSuggestionDismissed, setIsSuggestionDismissed] = useState(false);
  const [suggestionIndex, setSuggestionIndex] = useState(0);

  const currentValue = isControlled ? value : innerValue;
  const showClear = allowClear && !disabled && Boolean(currentValue);
  const suggestionGroups = useMemo(() => {
    const source = Array.isArray(aiSuggestions) && aiSuggestions.length > 0
      ? aiSuggestions
      : (typeof aiSuggestion === 'string' && aiSuggestion.trim().length > 0 ? [aiSuggestion] : []);
    return buildSuggestionGroupsFromFlatList(source, INPUT_LOCAL_FALLBACK_SUGGESTION_GROUPS);
  }, [aiSuggestion, aiSuggestions]);
  const activeSuggestions = suggestionGroups[suggestionIndex] || suggestionGroups[0] || [];
  const suggestionList = useMemo(
    () => activeSuggestions.map((item, index) => ({
      id: `input-ai-suggestion-${suggestionIndex}-${index}`,
      label: item,
      value: item,
    })),
    [activeSuggestions, suggestionIndex]
  );
  const showSuggestion = !disabled && !isSuggestionDismissed && suggestionList.length > 0;
  const canRefreshLocally = suggestionGroups.length > 1;
  const showAiRefresh = !disabled && suggestionList.length > 0
    && (canRefreshLocally || typeof onRefreshAiSuggestions === 'function');
  const activeButtonCount = (showClear ? 1 : 0) + (showAiRefresh ? 1 : 0);

  useEffect(() => {
    setIsSuggestionDismissed(false);
    setSuggestionIndex(0);
  }, [aiSuggestion, aiSuggestions]);

  const handleChange = useCallback((e) => {
    if (!isControlled) setInnerValue(e.target.value);
    onChange?.(e);
  }, [isControlled, onChange]);

  const handleClear = useCallback(() => {
    if (!isControlled) {
      setInnerValue('');
      if (inputRef.current) inputRef.current.value = '';
    }
    onClear?.();
    inputRef.current?.focus();
  }, [isControlled, onClear]);

  const handleAdoptSuggestion = useCallback((suggestion) => {
    if (!suggestion?.value) return;
    dispatchNativeInputValue(inputRef.current, suggestion.value);
    onAdoptSuggestion?.(suggestion.value);
    setIsSuggestionDismissed(true);
    inputRef.current?.focus();
  }, [onAdoptSuggestion]);

  const handleRefreshAiSuggestions = useCallback(() => {
    if (canRefreshLocally) {
      setSuggestionIndex((prev) => (prev + 1) % suggestionGroups.length);
    }
    onRefreshAiSuggestions?.();
    setIsSuggestionDismissed(false);
    inputRef.current?.focus();
  }, [canRefreshLocally, onRefreshAiSuggestions, suggestionGroups.length]);

  const wrapperCls = [
    WRAPPER_BASE,
    className,
  ].filter(Boolean).join(' ');

  const fieldCls = [
    FIELD_BASE,
    disabled ? DISABLED_CLASS : STATUS_CLASS[status],
    SIZE_CLASS,
  ].filter(Boolean).join(' ');

  const inputCls = [
    INPUT_BASE,
    getInputPaddingClasses(Boolean(suffix), activeButtonCount),
  ].filter(Boolean).join(' ');

  return (
    <div className={wrapperCls} style={style}>
      <div className={fieldCls} data-tfds-component="Input">
        {prefix ? <span className={ADDON_CLASS}>{prefix}</span> : null}
        <input
          ref={inputRef}
          className={inputCls}
          placeholder={placeholder}
          disabled={disabled}
          value={isControlled ? value : undefined}
          defaultValue={isControlled ? undefined : defaultValue}
          onChange={handleChange}
          {...rest}
        />
        {(showClear || showAiRefresh || suffix) ? (
          <span className={TRAILING_CLASS}>
            {showClear ? (
              <button
                type="button"
                className={CLEAR_CLASS}
                onClick={handleClear}
                aria-label="清除"
                tabIndex={-1}
              >
                <svg viewBox="0 0 16 16" fill="none" className="size-[16px]">
                  <circle cx="8" cy="8" r="7" fill="currentColor" fillOpacity="0.15" />
                  <path d="M5.5 5.5L10.5 10.5M10.5 5.5L5.5 10.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
                </svg>
              </button>
            ) : null}
            {showAiRefresh ? (
              <AiRefreshButton onClick={handleRefreshAiSuggestions} />
            ) : null}
            {suffix ? <span className={ADDON_CLASS}>{suffix}</span> : null}
          </span>
        ) : null}
      </div>
      {aiSuggestionsLoading ? (
        <AiSuggestionPanelSkeleton count={aiSuggestionsLoadingCount} />
      ) : null}
      {!aiSuggestionsLoading && showSuggestion ? (
        <AiSuggestionPanel
          suggestions={suggestionList}
          onSelect={handleAdoptSuggestion}
          getSuggestionKey={(suggestion) => suggestion.id}
          getSuggestionLabel={(suggestion) => suggestion.label}
          getSuggestionAriaLabel={(_, index) => `采纳 AI 推荐内容 ${index + 1}`}
        />
      ) : null}
    </div>
  );
}
