'use client';

import * as React from 'react';
import { Upload, X } from 'lucide-react';

import { Button, type ButtonProps } from '@/components/ui/button';
import { cn } from '@/lib/utils';

export interface FileInputButtonProps {
  /** File-picker `accept` attribute (MIME or extension list). */
  accept?: string;
  /** Allow picking more than one file. Default: false. */
  multiple?: boolean;
  /** Required: handler invoked with the picked FileList contents. */
  onFilesPicked: (files: File[]) => void;
  /** Button label. Default: "Choose file" / "Choose files". */
  label?: string;
  /** Show an Upload icon before the label. Default: true. */
  showIcon?: boolean;
  /** Button variant. Default: 'outline'. */
  variant?: ButtonProps['variant'];
  /** Button size. Default: 'sm'. */
  size?: ButtonProps['size'];
  /** Disable the picker (e.g. while a previous upload is in flight). */
  disabled?: boolean;
  /** Optional className applied to the wrapper. */
  className?: string;
  /** Optional className applied to the trigger Button. */
  buttonClassName?: string;
  /** Tooltip text on the trigger Button. */
  title?: string;
  /**
   * When true, renders the selected filename next to a clear (×) button
   * underneath the picker - same idiom as the expense form. Default:
   * false (the caller manages its own filename display).
   */
  showSelectedFilename?: boolean;
}

/**
 * Styled file-picker primitive - replaces the raw browser-default
 * `<input type="file">` UI that looks different across Chromium /
 * Safari / Firefox. Renders a Button + hidden input; the Button forwards
 * clicks to the input. Use everywhere we'd otherwise render a raw file
 * input.
 */
export const FileInputButton = React.forwardRef<HTMLInputElement, FileInputButtonProps>(
  function FileInputButton(
    {
      accept,
      multiple = false,
      onFilesPicked,
      label,
      showIcon = true,
      variant = 'outline',
      size = 'sm',
      disabled,
      className,
      buttonClassName,
      title,
      showSelectedFilename = false,
    },
    forwardedRef,
  ) {
    const inputRef = React.useRef<HTMLInputElement>(null);
    const [selected, setSelected] = React.useState<File[]>([]);

    React.useImperativeHandle(forwardedRef, () => inputRef.current as HTMLInputElement);

    const computedLabel = label ?? (multiple ? 'Choose files' : 'Choose file');

    function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
      const list = e.target.files;
      if (!list || list.length === 0) return;
      const files = Array.from(list);
      setSelected(files);
      onFilesPicked(files);
    }

    function clear() {
      setSelected([]);
      if (inputRef.current) inputRef.current.value = '';
    }

    return (
      <div className={cn('inline-flex flex-col gap-2', className)}>
        <Button
          type="button"
          variant={variant}
          size={size}
          disabled={disabled}
          title={title}
          className={buttonClassName}
          onClick={() => inputRef.current?.click()}
        >
          {showIcon ? <Upload aria-hidden /> : null}
          {computedLabel}
        </Button>
        <input
          ref={inputRef}
          type="file"
          accept={accept}
          multiple={multiple}
          onChange={handleChange}
          className="hidden"
          aria-hidden
          tabIndex={-1}
        />
        {showSelectedFilename && selected.length > 0 ? (
          <div className="flex items-center gap-2 text-xs text-muted-foreground">
            <span className="truncate" title={selected.map((f) => f.name).join(', ')}>
              {selected.length === 1 ? selected[0]!.name : `${selected.length} files selected`}
            </span>
            <button
              type="button"
              onClick={clear}
              className="text-muted-foreground hover:text-foreground"
              aria-label="Clear selection"
            >
              <X className="h-3 w-3" aria-hidden />
            </button>
          </div>
        ) : null}
      </div>
    );
  },
);
