"use client";

import * as React from "react";
import { cn } from "@/lib/utils";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

interface FormFieldProps {
  label: string;
  description?: string;
  error?: string;
  required?: boolean;
  children: React.ReactNode;
  className?: string;
  htmlFor?: string;
}

export function FormField({
  label,
  description,
  error,
  required,
  children,
  className,
  htmlFor,
}: FormFieldProps) {
  return (
    <div className={cn("space-y-1.5", className)}>
      <Label htmlFor={htmlFor} className="text-sm font-medium text-foreground">
        {label}
        {required && (
          <span className="text-destructive ml-1" aria-hidden="true">
            *
          </span>
        )}
      </Label>
      {description && !error && (
        <p className="text-sm text-muted-foreground">{description}</p>
      )}
      {children}
      {error && (
        <p className="text-sm text-destructive" role="alert">
          {error}
        </p>
      )}
      {description && error && (
        <p className="text-sm text-muted-foreground">{description}</p>
      )}
    </div>
  );
}

interface InputFieldProps extends React.InputHTMLAttributes<HTMLInputElement> {
  label: string;
  description?: string;
  error?: string;
  required?: boolean;
  type?: "text" | "email" | "number" | "password" | "url" | "tel";
}

export function InputField({
  label,
  description,
  error,
  required,
  type = "text",
  className,
  id,
  ...props
}: InputFieldProps) {
  const fieldId = id || label.toLowerCase().replace(/\s+/g, "-");

  return (
    <FormField
      label={label}
      description={description}
      error={error}
      required={required}
      htmlFor={fieldId}
    >
      <Input
        id={fieldId}
        type={type}
        className={cn(
          error &&
            "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
          className,
        )}
        aria-invalid={!!error}
        aria-describedby={
          error
            ? `${fieldId}-error`
            : description
              ? `${fieldId}-desc`
              : undefined
        }
        {...props}
      />
    </FormField>
  );
}

interface TextareaFieldProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
  label: string;
  description?: string;
  error?: string;
  required?: boolean;
  rows?: number;
}

export function TextareaField({
  label,
  description,
  error,
  required,
  rows = 4,
  className,
  id,
  ...props
}: TextareaFieldProps) {
  const fieldId = id || label.toLowerCase().replace(/\s+/g, "-");

  return (
    <FormField
      label={label}
      description={description}
      error={error}
      required={required}
      htmlFor={fieldId}
    >
      <Textarea
        id={fieldId}
        rows={rows}
        className={cn(
          error &&
            "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
          className,
        )}
        aria-invalid={!!error}
        aria-describedby={
          error
            ? `${fieldId}-error`
            : description
              ? `${fieldId}-desc`
              : undefined
        }
        {...props}
      />
    </FormField>
  );
}

interface SelectFieldProps {
  label: string;
  description?: string;
  error?: string;
  required?: boolean;
  placeholder?: string;
  options: { value: string; label: string }[];
  value: string;
  onChange: (value: string) => void;
  className?: string;
  id?: string;
  disabled?: boolean;
}

export function SelectField({
  label,
  description,
  error,
  required,
  placeholder,
  options,
  value,
  onChange,
  className,
  id,
  disabled,
}: SelectFieldProps) {
  const fieldId = id || label.toLowerCase().replace(/\s+/g, "-");

  return (
    <FormField
      label={label}
      description={description}
      error={error}
      required={required}
      htmlFor={fieldId}
    >
      <Select
        items={options}
        value={value}
        onValueChange={(v) => onChange(v ?? "")}
        disabled={disabled}
      >
        <SelectTrigger
          id={fieldId}
          className={cn(
            error && "aria-invalid:border-destructive w-full",
            className,
          )}
          aria-invalid={!!error}
        >
          <SelectValue placeholder={placeholder} />
        </SelectTrigger>
        <SelectContent>
          {options.map((option) => (
            <SelectItem key={option.value} value={option.value}>
              {option.label}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </FormField>
  );
}

interface NumberInputFieldProps extends Omit<InputFieldProps, "type"> {
  min?: number;
  max?: number;
  step?: number;
  prefix?: string;
  suffix?: string;
}

export function NumberInputField({
  label,
  description,
  error,
  required,
  min,
  max,
  step,
  prefix,
  suffix,
  className,
  id,
  ...props
}: NumberInputFieldProps) {
  const fieldId = id || label.toLowerCase().replace(/\s+/g, "-");

  return (
    <FormField
      label={label}
      description={description}
      error={error}
      required={required}
      htmlFor={fieldId}
    >
      <div className="relative">
        {prefix && (
          <span className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground text-sm">
            {prefix}
          </span>
        )}
        <Input
          id={fieldId}
          type="number"
          min={min}
          max={max}
          step={step}
          className={cn(
            prefix && "pl-8",
            suffix && "pr-8",
            error &&
              "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
            className,
          )}
          aria-invalid={!!error}
          aria-describedby={
            error
              ? `${fieldId}-error`
              : description
                ? `${fieldId}-desc`
                : undefined
          }
          {...props}
        />
        {suffix && (
          <span className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground text-sm">
            {suffix}
          </span>
        )}
      </div>
    </FormField>
  );
}
