import { useRef, useState, type DragEvent } from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { FieldError } from './FieldError';

type Kind = 'image' | 'document';

type Props = {
  name: string;
  label: string;
  folder?: string;
  hint?: string;
  accept?: string;
  maxSizeMb?: number;
  kind?: Kind;
};

const ACCEPT: Record<Kind, string> = {
  image: 'image/png,image/jpeg,image/webp,image/svg+xml,image/gif',
  document: 'application/pdf,.pdf',
};

const HELP_TEXT: Record<Kind, string> = {
  image: 'png, jpg, webp, svg, gif',
  document: 'pdf uniquement',
};

function fileNameFromUrl(url: string): string {
  try {
    const clean = url.split('?')[0];
    const segments = clean.split('/');
    return segments[segments.length - 1] || url;
  } catch {
    return url;
  }
}

export function FileUploadField({
  name,
  label,
  folder = '',
  hint,
  accept,
  maxSizeMb,
  kind = 'image',
}: Props) {
  const { control } = useFormContext();
  const inputRef = useRef<HTMLInputElement>(null);
  const [hover, setHover] = useState(false);
  const [busy, setBusy] = useState(false);
  const [localError, setLocalError] = useState<string | null>(null);

  const effectiveAccept = accept ?? ACCEPT[kind];
  const effectiveMax = maxSizeMb ?? (kind === 'document' ? 8 : 5);

  return (
    <Controller
      name={name}
      control={control}
      render={({ field }) => {
        const url: string = field.value || '';

        const upload = async (file: File) => {
          setLocalError(null);
          if (file.size > effectiveMax * 1024 * 1024) {
            setLocalError(`Fichier trop lourd (max ${effectiveMax} Mo).`);
            return;
          }
          setBusy(true);
          try {
            const fd = new FormData();
            fd.append('file', file);
            fd.append('kind', kind);
            if (folder) fd.append('folder', folder);
            const res = await fetch('/api/upload', { method: 'POST', body: fd });
            const data = await res.json();
            if (!res.ok || !data.url) {
              setLocalError(data?.error || 'upload échoué');
              return;
            }
            field.onChange(data.url);
          } catch (e) {
            setLocalError((e as Error).message || 'upload échoué');
          } finally {
            setBusy(false);
          }
        };

        const onDrop = (e: DragEvent<HTMLDivElement>) => {
          e.preventDefault();
          setHover(false);
          const file = e.dataTransfer.files?.[0];
          if (file) upload(file);
        };

        return (
          <div>
            <span className="block font-mono text-xs uppercase tracking-widest text-[color:var(--color-cyan)] mb-1.5">
              {label}
            </span>
            {hint && (
              <span className="block font-mono text-[10px] text-[color:var(--color-text-dim)] mb-1.5">
                {hint}
              </span>
            )}
            <div className="flex flex-col sm:flex-row sm:items-start gap-3">
              {url && kind === 'image' ? (
                <div className="relative shrink-0">
                  <img
                    src={url}
                    alt=""
                    className="w-28 h-28 object-cover border border-[color:var(--color-cyan)] rounded"
                  />
                  <span className="sticker absolute -top-2 -left-2 text-[color:var(--color-cyan)]">
                    ok
                  </span>
                </div>
              ) : null}

              {url && kind === 'document' ? (
                <div className="relative shrink-0 w-full sm:w-44 p-3 border border-[color:var(--color-cyan)] rounded bg-[color:var(--color-surface-2)] flex flex-col gap-1">
                  <span className="font-mono text-[10px] uppercase tracking-widest text-[color:var(--color-cyan)]">
                    pdf actuel
                  </span>
                  <span className="font-mono text-[11px] text-[color:var(--color-text)] truncate">
                    {fileNameFromUrl(url)}
                  </span>
                  <a
                    href={url}
                    target="_blank"
                    rel="noopener"
                    className="font-mono text-[10px] uppercase tracking-widest text-[color:var(--color-acid)] hover:underline"
                  >
                    voir le fichier ↗
                  </a>
                </div>
              ) : null}

              <div
                onDragEnter={(e) => {
                  e.preventDefault();
                  setHover(true);
                }}
                onDragOver={(e) => {
                  e.preventDefault();
                  setHover(true);
                }}
                onDragLeave={() => setHover(false)}
                onDrop={onDrop}
                onClick={() => inputRef.current?.click()}
                role="button"
                tabIndex={0}
                onKeyDown={(e) => {
                  if (e.key === 'Enter' || e.key === ' ') {
                    e.preventDefault();
                    inputRef.current?.click();
                  }
                }}
                className={`flex-1 cursor-pointer p-4 rounded text-center transition-all ${
                  hover
                    ? 'neon-border-cyan glow-cyan'
                    : 'border border-dashed border-[color:var(--color-border)] hover:border-[color:var(--color-cyan)]'
                }`}
              >
                {busy ? (
                  <div className="flex items-center justify-center gap-2 font-mono text-xs uppercase tracking-widest text-[color:var(--color-acid)]">
                    <span className="led led-acid animate-led-red" />
                    upload en cours…
                  </div>
                ) : (
                  <div className="flex flex-col items-center gap-1 font-mono text-xs uppercase tracking-widest text-[color:var(--color-text-muted)]">
                    <span className="text-[color:var(--color-cyan)]">
                      {url ? '↻ remplacer' : '↑ glisser-déposer'}
                    </span>
                    <span className="text-[10px] text-[color:var(--color-text-dim)] normal-case tracking-normal">
                      ou cliquer · {HELP_TEXT[kind]} (max {effectiveMax} Mo)
                    </span>
                  </div>
                )}
              </div>

              {url && (
                <button
                  type="button"
                  onClick={() => field.onChange('')}
                  className="self-start sm:self-auto shrink-0 px-2 py-1 font-mono text-xs uppercase tracking-widest text-[color:var(--color-magenta)] border border-[color:var(--color-magenta)] rounded hover:bg-[color:var(--color-magenta)] hover:text-[color:var(--color-bg)] transition-colors"
                >
                  ×
                </button>
              )}
            </div>

            <input
              ref={inputRef}
              type="file"
              accept={effectiveAccept}
              className="hidden"
              onChange={(e) => {
                const file = e.target.files?.[0];
                if (file) upload(file);
                e.target.value = '';
              }}
            />

            {url && (
              <p className="mt-1 font-mono text-[10px] text-[color:var(--color-text-dim)] truncate">
                {url}
              </p>
            )}

            {localError && (
              <p className="mt-1 flex items-center gap-2 font-mono text-xs text-[color:var(--color-magenta)]">
                <span className="led led-red animate-led-red" />
                {localError}
              </p>
            )}

            <FieldError name={name} />
          </div>
        );
      }}
    />
  );
}
