'use client';

import { useId, useState } from 'react';
import { useFormStatus } from 'react-dom';
import { Eye, EyeOff, LoaderCircle } from 'lucide-react';
import { cn } from '@/lib/cn';
import { useMessages } from '@/i18n/client';
import { Button } from './Button';

const inputBase =
  'h-12 w-full rounded-2xl bg-surface px-4 text-[15px] text-ink ring-1 ring-line transition-shadow placeholder:text-subtle focus:ring-2 focus:ring-ink/80 focus:outline-none aria-invalid:ring-fire/70';

interface FieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'id'> {
  label: string;
  hint?: string;
  errors?: string[];
}

export function Field({ label, hint, errors, type = 'text', className, ...input }: FieldProps) {
  const id = useId();
  const t = useMessages().modals;
  const [reveal, setReveal] = useState(false);
  const isPassword = type === 'password';
  const describedBy = errors?.length ? `${id}-error` : hint ? `${id}-hint` : undefined;

  return (
    <div className={className}>
      <label htmlFor={id} className="block text-[13px] font-medium text-ink">
        {label}
      </label>
      <div className="relative mt-2">
        <input
          id={id}
          type={isPassword && reveal ? 'text' : type}
          aria-invalid={errors?.length ? true : undefined}
          aria-describedby={describedBy}
          className={cn(inputBase, isPassword && 'pr-12')}
          {...input}
        />
        {isPassword && (
          <button
            type="button"
            onClick={() => setReveal((v) => !v)}
            aria-label={reveal ? t.hidePassword : t.showPassword}
            className="absolute inset-y-0 right-1.5 my-auto inline-flex size-9 items-center justify-center rounded-full text-subtle hover:text-ink"
          >
            {reveal ? <EyeOff className="size-4" /> : <Eye className="size-4" />}
          </button>
        )}
      </div>
      {errors?.length ? (
        <p id={`${id}-error`} className="mt-2 text-[13px] text-fire">
          {errors[0]}
        </p>
      ) : hint ? (
        <p id={`${id}-hint`} className="mt-2 text-[13px] text-muted">
          {hint}
        </p>
      ) : null}
    </div>
  );
}

interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'id'> {
  label: string;
  errors?: string[];
  options: { value: string; label: string }[];
}

export function SelectField({ label, errors, options, className, ...select }: SelectProps) {
  const id = useId();
  return (
    <div className={className}>
      <label htmlFor={id} className="block text-[13px] font-medium text-ink">
        {label}
      </label>
      <select
        id={id}
        aria-invalid={errors?.length ? true : undefined}
        className={cn(inputBase, 'mt-2 appearance-none bg-[url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2716%27 height=%2716%27 fill=%27none%27 stroke=%27%236B7285%27 stroke-width=%272%27%3E%3Cpath d=%27m4 6 4 4 4-4%27/%3E%3C/svg%3E")] bg-[position:right_16px_center] bg-no-repeat pr-10')}
        {...select}
      >
        {options.map((o) => (
          <option key={o.value} value={o.value}>
            {o.label}
          </option>
        ))}
      </select>
      {errors?.length ? <p className="mt-2 text-[13px] text-fire">{errors[0]}</p> : null}
    </div>
  );
}

export function SubmitButton({ children, className }: { children: React.ReactNode; className?: string }) {
  const { pending } = useFormStatus();
  return (
    <Button type="submit" disabled={pending} aria-busy={pending} className={cn('w-full', className)}>
      {pending && <LoaderCircle className="size-4 animate-spin" aria-hidden />}
      {children}
    </Button>
  );
}

export function FormMessage({ children }: { children?: React.ReactNode }) {
  if (!children) return null;
  return (
    <p role="alert" className="rounded-2xl bg-fire/[0.07] px-4 py-3 text-[13px] text-fire ring-1 ring-fire/20">
      {children}
    </p>
  );
}
