import * as React from "react";
import { Search, X } from "lucide-react";
import { cn } from "@/lib/utils";

export const inputBase =
  "flex h-9 w-full rounded-md border border-border bg-surface px-3 py-1 text-sm text-fg shadow-xs transition-colors placeholder:text-fg-subtle hover:border-border-strong focus:border-ring focus:outline-none focus:ring-2 focus:ring-ring/25 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-negative-500 aria-invalid:focus:ring-negative-500/25";

export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "prefix"> {
  prefix?: React.ReactNode;
  suffix?: React.ReactNode;
}

const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, prefix, suffix, ...props }, ref) => {
  if (prefix || suffix) {
    return (
      <div className="relative flex items-center">
        {prefix ? <span className="pointer-events-none absolute left-3 text-xs text-fg-muted">{prefix}</span> : null}
        <input type={type} className={cn(inputBase, prefix && "pl-9", suffix && "pr-14", className)} ref={ref} {...props} />
        {suffix ? <span className="pointer-events-none absolute right-3 text-xs font-medium text-fg-muted">{suffix}</span> : null}
      </div>
    );
  }
  return <input type={type} className={cn(inputBase, className)} ref={ref} {...props} />;
});
Input.displayName = "Input";

const Textarea = React.forwardRef<HTMLTextAreaElement, React.TextareaHTMLAttributes<HTMLTextAreaElement>>(({ className, ...props }, ref) => (
  <textarea className={cn(inputBase, "h-auto min-h-[80px] py-2 leading-relaxed", className)} ref={ref} {...props} />
));
Textarea.displayName = "Textarea";

export interface SearchInputProps extends Omit<InputProps, "onChange" | "value"> {
  value: string;
  onChange: (v: string) => void;
}
function SearchInput({ value, onChange, className, placeholder = "Search…", prefix: _prefix, suffix: _suffix, ...props }: SearchInputProps) {
  void _prefix;
  void _suffix;
  return (
    <div className={cn("relative flex items-center", className)}>
      <Search className="pointer-events-none absolute left-3 size-4 text-fg-subtle" />
      <input value={value} onChange={(e) => onChange(e.target.value)} placeholder={placeholder} className={cn(inputBase, "pl-9 pr-8")} {...props} />
      {value ? (
        <button type="button" onClick={() => onChange("")} className="absolute right-2 rounded-sm p-1 text-fg-subtle hover:bg-surface-2 hover:text-fg" aria-label="Clear search">
          <X className="size-3.5" />
        </button>
      ) : null}
    </div>
  );
}

const Label = React.forwardRef<HTMLLabelElement, React.LabelHTMLAttributes<HTMLLabelElement> & { required?: boolean }>(({ className, children, required, ...props }, ref) => (
  <label ref={ref} className={cn("text-xs font-medium text-fg-muted leading-none", className)} {...props}>
    {children}
    {required ? <span className="ml-0.5 text-negative-500">*</span> : null}
  </label>
));
Label.displayName = "Label";

/** Field = label + control + hint/error; the standard form row everywhere. */
function Field({ label, hint, error, required, children, className, htmlFor }: { label?: React.ReactNode; hint?: React.ReactNode; error?: string | null; required?: boolean; children: React.ReactNode; className?: string; htmlFor?: string }) {
  return (
    <div className={cn("flex flex-col gap-1.5", className)}>
      {label ? (
        <Label htmlFor={htmlFor} required={required}>
          {label}
        </Label>
      ) : null}
      {children}
      {error ? <p className="text-xs text-negative-600">{error}</p> : hint ? <p className="text-xs text-fg-subtle">{hint}</p> : null}
    </div>
  );
}

const NativeSelect = React.forwardRef<HTMLSelectElement, React.SelectHTMLAttributes<HTMLSelectElement>>(({ className, children, ...props }, ref) => (
  <div className="relative">
    <select ref={ref} className={cn(inputBase, "appearance-none pr-8 cursor-pointer", className)} {...props}>
      {children}
    </select>
    <svg className="pointer-events-none absolute right-2.5 top-1/2 size-4 -translate-y-1/2 text-fg-subtle" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="m6 9 6 6 6-6" />
    </svg>
  </div>
));
NativeSelect.displayName = "NativeSelect";

export { Input, Textarea, SearchInput, Label, Field, NativeSelect };
