import { forwardRef } from "react";
import type { InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes } from "react";
import { FOCUS_RING_TIGHT_CLASSES } from "@/components/ui/styles";
import { cn } from "@/lib/utils";

export type FieldSize = "sm" | "md";

const SIZE_CLASSES: Record<FieldSize, string> = {
  sm: "px-3 py-1.5 text-sm",
  md: "px-3 py-2 text-sm",
};

// No `w-full` here on purpose — most call sites live in a `flex flex-col`
// label, where flexbox's default `align-items: stretch` already fills the
// width. Baking in `w-full` would fight any deliberately narrow input (e.g.
// a numeric "display order" field) via a same-specificity Tailwind class
// collision. Add `className="w-full"` explicitly on the rare call site that
// needs it outside a stretching flex-col context.
const BASE_CLASSES =
  "rounded-lg border border-kolabora-neutral-dark/20 disabled:opacity-50 disabled:cursor-not-allowed " + FOCUS_RING_TIGHT_CLASSES;

export function fieldClasses(size: FieldSize = "md", className = ""): string {
  return cn(BASE_CLASSES, SIZE_CLASSES[size], className);
}

export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
  size?: FieldSize;
}

export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
  { size = "md", className, ...props },
  ref,
) {
  return <input ref={ref} className={fieldClasses(size, className)} {...props} />;
});

export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
  size?: FieldSize;
}

export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(
  { size = "md", className, ...props },
  ref,
) {
  return <textarea ref={ref} className={fieldClasses(size, className)} {...props} />;
});

export interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> {
  size?: FieldSize;
}

export const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(
  { size = "md", className, ...props },
  ref,
) {
  return <select ref={ref} className={fieldClasses(size, className)} {...props} />;
});

// Native `<input type="file">` renders its picker trigger via the
// `::file-selector-button` pseudo-element with OS-default button chrome —
// visually disconnected from every other control in the design system, so
// it doesn't read as clickable. Tailwind's `file:` variant targets that
// pseudo-element directly, styled to match `buttonClasses("secondary", "sm")`
// (neutral/gray, not primary orange — this is a picker action, not the CTA).
const FILE_BASE_CLASSES =
  "block text-sm text-kolabora-neutral-dark disabled:opacity-50 disabled:cursor-not-allowed " +
  "file:mr-3 file:cursor-pointer file:rounded-full file:border file:border-kolabora-neutral-dark/20 " +
  "file:bg-kolabora-neutral-white file:px-4 file:py-2 file:text-sm file:font-medium file:text-kolabora-neutral-dark " +
  "file:transition-colors hover:file:bg-kolabora-neutral-dark/5 disabled:file:pointer-events-none " +
  "focus-visible:outline-none focus-visible:file:ring-2 focus-visible:file:ring-kolabora-primary focus-visible:file:ring-offset-1";

export function fileFieldClasses(className = ""): string {
  return cn(FILE_BASE_CLASSES, className);
}

export type FileInputProps = InputHTMLAttributes<HTMLInputElement>;

export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(function FileInput(
  { className, ...props },
  ref,
) {
  return <input ref={ref} type="file" className={fileFieldClasses(className)} {...props} />;
});
