'use client';
import { useRef, useState } from 'react';
import { api } from '@/lib/api';
import { useAuth } from '@/lib/auth-context';
import { useDialog } from '@/components/dialog';
import { FloatInput } from '@/components/float';
import { IconEdit, IconTrash } from '@/components/ui';

export interface StagedLink { url: string; title: string }
export interface AttachTarget { action_id?: number; sub_action_id?: number; sample_id?: number; }

export const emptyLink = (): StagedLink => ({ url: '', title: '' });

/** Parent-owned staging state (files + link rows, attached automatically on submit). */
export function useStagedAttachments() {
  const [files, setFiles] = useState<File[]>([]);
  const [links, setLinks] = useState<StagedLink[]>([]);
  const clear = () => { setFiles([]); setLinks([]); };
  const complete = links.filter((l) => l.url.trim() && l.title.trim());
  return { files, setFiles, links, setLinks, clear, complete, count: files.length + complete.length };
}

/** Validate link rows: fully-empty rows are skipped, partial/invalid rows report errors. */
export function linkRowErrors(links: StagedLink[]): string[] {
  const errs: string[] = [];
  links.forEach((l, i) => {
    const u = l.url.trim(); const t = l.title.trim();
    if (!u && !t) return;
    if (!/^https?:\/\/.+\..+/.test(u)) errs.push(`Link ${i + 1}: enter a valid link starting with http(s)://`);
    else if (t.length < 2) errs.push(`Link ${i + 1}: title needs at least 2 characters`);
  });
  return errs;
}

/** Upload staged files + complete links to an existing record. Returns per-item failure messages. */
export async function uploadStaged(target: AttachTarget, files: File[], links: StagedLink[]): Promise<string[]> {
  const failed: string[] = [];
  for (const f of files) {
    const fd = new FormData();
    fd.append('file', f);
    if (target.sub_action_id) fd.append('sub_action_id', String(target.sub_action_id));
    else if (target.action_id) fd.append('action_id', String(target.action_id));
    else if (target.sample_id) fd.append('sample_id', String(target.sample_id));
    try { await api.upload('/api/v1/documents', fd); }
    catch (e: any) { failed.push(`${f.name}: ${e.message}`); }
  }
  for (const l of links) {
    if (!l.url.trim() || !l.title.trim()) continue;
    try { await api.post('/api/v1/documents/links', { ...target, url: l.url.trim(), title: l.title.trim() }); }
    catch (e: any) { failed.push(`${l.title}: ${e.message}`); }
  }
  return failed;
}

/**
 * One saved attachment with edit/delete (audited server-side).
 * Staff manage any org attachment; employees manage their own uploads.
 */
export function AttachmentRow({ d, badge, onChanged }: {
  d: any; badge?: React.ReactNode; onChanged: () => void;
}) {
  const { user } = useAuth();
  const { confirmDialog, notify } = useDialog();
  const [editing, setEditing] = useState(false);
  const [title, setTitle] = useState(d.original_file_name ?? '');
  const [url, setUrl] = useState(d.file_type === 'link' ? d.storage_path : '');
  const [desc, setDesc] = useState(d.description ?? '');
  const [busy, setBusy] = useState(false);
  const canManage = user?.role !== 'employee' || d.uploaded_by === user?.id;
  const isLink = d.file_type === 'link';
  if (!editing) {
    return (
      <p className="text-sm border-t py-1 flex flex-wrap gap-2 items-center">
        {isLink
          ? <a className="underline font-medium" href={d.storage_path} target="_blank" rel="noopener noreferrer">🔗 {d.original_file_name}</a>
          : <a className="underline font-medium" href={`/api/v1/documents/${d.id}/download`}>📄 {d.original_file_name}</a>}
        {badge}
        <span className="text-xs text-slate-500 ml-auto">by {d.uploader_name}</span>
        {canManage && (
          <span className="flex gap-1">
            <button type="button" className="btn-plain" aria-label={`Edit ${d.original_file_name}`} title="Edit" onClick={() => {
              setTitle(d.original_file_name ?? ''); setUrl(isLink ? d.storage_path : ''); setDesc(d.description ?? ''); setEditing(true);
            }}><IconEdit /></button>
            <button type="button" className="btn-plain" aria-label={`Delete ${d.original_file_name}`} title="Delete" onClick={async () => {
              if (!await confirmDialog(`Delete attachment "${d.original_file_name}"?`, { title: 'Delete attachment', confirmLabel: 'Delete' })) return;
              try { await api.del(`/api/v1/documents/${d.id}`); notify('Attachment deleted.', { tone: 'success' }); onChanged(); }
              catch (e: any) { notify(e.message, { tone: 'error' }); }
            }}><IconTrash /></button>
          </span>
        )}
      </p>
    );
  }
  return (
    <div className="border-t py-2 space-y-2">
      <div className="grid md:grid-cols-2 gap-2">
        <FloatInput label="Title" id={`doc-t-${d.id}`} value={title} onChange={(e) => setTitle(e.target.value)} />
        {isLink && <FloatInput label="URL (https://…)" id={`doc-u-${d.id}`} type="url" value={url} onChange={(e) => setUrl(e.target.value)} />}
      </div>
      <FloatInput label="Description (optional)" id={`doc-d-${d.id}`} value={desc} onChange={(e) => setDesc(e.target.value)} />
      <div className="flex gap-2">
        <button className="btn-primary btn-sm" disabled={busy} onClick={async () => {
          if (title.trim().length < 2) { notify('Title needs at least 2 characters.', { tone: 'error' }); return; }
          if (isLink && !/^https?:\/\/.+\..+/.test(url.trim())) { notify('Enter a valid link starting with http(s)://', { tone: 'error' }); return; }
          setBusy(true);
          try {
            await api.patch(`/api/v1/documents/${d.id}`, {
              title: title.trim(), description: desc.trim() || null,
              ...(isLink ? { url: url.trim() } : {}),
            });
            notify('Attachment updated.', { tone: 'success' });
            setEditing(false); onChanged();
          } catch (e: any) { notify(e.message, { tone: 'error' }); }
          finally { setBusy(false); }
        }}>{busy ? 'Saving…' : 'Save'}</button>
        <button className="btn-ghost btn-sm" onClick={() => setEditing(false)}>Cancel</button>
      </div>
    </div>
  );
}

/**
 * Staging UI: full-width drag & drop file zone + repeatable half-half
 * Drive URL/title rows (plus icon adds more). Everything attaches
 * automatically when the record is saved — no per-link button.
 * Each grid cell owns its error line, so rows never shift unevenly.
 */
export function AttachmentComposer({ idPrefix, files, setFiles, links, setLinks }: {
  idPrefix: string;
  files: File[]; setFiles: (f: File[] | ((p: File[]) => File[])) => void;
  links: StagedLink[]; setLinks: (l: StagedLink[] | ((p: StagedLink[]) => StagedLink[])) => void;
}) {
  const inputRef = useRef<HTMLInputElement>(null);
  const [drag, setDrag] = useState(false);
  const addFiles = (list: FileList | null) => {
    if (!list?.length) return;
    setFiles((f) => [...f, ...Array.from(list)]);
  };
  const setRow = (i: number, k: 'url' | 'title', val: string) => {
    setLinks((all) => all.map((r, j) => (j === i ? { ...r, [k]: val } : r)));
  };
  return (
    <div className="space-y-2">
      <div
        role="button" tabIndex={0} aria-label="Attach files: drag and drop or browse"
        onClick={() => inputRef.current?.click()}
        onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') inputRef.current?.click(); }}
        onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
        onDragLeave={() => setDrag(false)}
        onDrop={(e) => { e.preventDefault(); setDrag(false); addFiles(e.dataTransfer.files); }}
        className={`w-full rounded-xl border-2 border-dashed p-4 text-center cursor-pointer transition ${drag ? 'border-slate-900 bg-slate-100' : ''}`}
        style={{ borderColor: drag ? undefined : 'var(--line)' }}
      >
        <input ref={inputRef} type="file" multiple className="hidden" aria-label="Attach files"
          onChange={(e) => { addFiles(e.target.files); e.target.value = ''; }} />
        <p className="text-sm font-medium">Drag &amp; drop files here, or <span className="underline">browse</span></p>
        <p className="hint mt-0.5">Multiple files allowed</p>
      </div>
      {files.length > 0 && (
        <div className="flex flex-wrap gap-1.5">
          {files.map((f, i) => (
            <span key={`${f.name}-${i}`} className="badge bg-slate-100">📄 {f.name}
              <button type="button" className="ml-1 font-bold" aria-label={`Remove ${f.name}`}
                onClick={() => setFiles((all) => all.filter((_, j) => j !== i))}>✕</button>
            </span>
          ))}
        </div>
      )}
      {links.map((row, i) => (
        <div key={i} className="grid grid-cols-[1fr_1fr_auto] gap-2 items-start">
          <FloatInput label="Drive / share link (https://…)" id={`${idPrefix}-link-url-${i}`} type="url"
            value={row.url} onChange={(e) => setRow(i, 'url', e.target.value)} />
          <FloatInput label="Link title" id={`${idPrefix}-link-title-${i}`}
            value={row.title} onChange={(e) => setRow(i, 'title', e.target.value)} />
          <button type="button" className="btn-plain mt-3" aria-label={`Remove link ${i + 1}`} title="Remove link"
            onClick={() => setLinks((all) => all.filter((_, j) => j !== i))}>✕</button>
        </div>
      ))}
      <button type="button" className="btn-ghost btn-sm" onClick={() => setLinks((all) => [...all, emptyLink()])}>+ Add link</button>
    </div>
  );
}
