'use client';
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import Link from 'next/link';
import { motion } from 'framer-motion';
import { api } from '@/lib/api';
import { useAuth } from '@/lib/auth-context';
import { formatDate } from '@/lib/format';
import { useDialog } from '@/components/dialog';

const COLS = ['Open', 'Assigned', 'In Progress', 'On Hold', 'Completed', 'Overdue', 'Cancelled'];

const PRIORITY_BAR: Record<string, string> = {
  Critical: 'bg-red-500', High: 'bg-orange-400', Medium: 'bg-blue-500', Low: 'bg-slate-300',
};

type Card = {
  key: string; kind: 'dev' | 'capa'; id: number; ref: string; title: string;
  status: string; target_date: string | null; assignee_name: string | null;
  assigned_employee_id: number | null; priority: string | null; parent_ref: string | null;
  parent_id: number | null; link: string;
};

const effStatus = (c: Card, overdue: boolean) => (overdue ? 'Overdue' : c.status);
const initials = (n: string | null) => (n ?? '?').trim().split(/\s+/).map((w) => w[0]).join('').slice(0, 2).toUpperCase();

export default function WorkflowBoardPage() {
  const { user } = useAuth();
  const { notify } = useDialog();
  const devQ = useQuery({ queryKey: ['kanban-dev'], queryFn: () => api.get('/api/v1/actions?limit=100') });
  const capaQ = useQuery({ queryKey: ['kanban-capa'], queryFn: () => api.get('/api/v1/sub-actions?limit=200') });
  // Optimistic status overrides while a drop is saving (keyed by card key).
  const [moves, setMoves] = useState<Record<string, string>>({});
  const [dragKey, setDragKey] = useState<string | null>(null);
  const [overCol, setOverCol] = useState<string | null>(null);
  const [busyKey, setBusyKey] = useState<string | null>(null);
  const [kindFilter, setKindFilter] = useState<'all' | 'dev' | 'capa'>('all');
  const [search, setSearch] = useState('');

  const devs: Card[] = (devQ.data?.data ?? []).map((a: any) => ({
    key: `d${a.id}`, kind: 'dev', id: a.id, ref: a.reference_number, title: a.title,
    status: moves[`d${a.id}`] ?? a.status, target_date: a.target_date ?? null,
    assignee_name: a.assignee_name ?? null, assigned_employee_id: a.assigned_employee_id ?? null,
    priority: a.priority ?? null, parent_ref: null, parent_id: null, link: `/actions/${a.id}`,
    _overdue: moves[`d${a.id}`] ? false : !!a.computed_overdue,
  }));
  const capas: Card[] = (capaQ.data?.data ?? []).map((s: any) => ({
    key: `c${s.id}`, kind: 'capa', id: s.id, ref: s.sub_reference_number, title: s.title,
    status: moves[`c${s.id}`] ?? s.status, target_date: s.target_date ? String(s.target_date).slice(0, 10) : null,
    assignee_name: s.assignee_name ?? null, assigned_employee_id: s.assigned_employee_id ?? null,
    priority: s.priority ?? null, parent_ref: s.parent_ref ?? null, parent_id: s.action_id ?? null,
    link: `/actions/${s.action_id}`,
    _overdue: moves[`c${s.id}`] ? false : !!s.computed_overdue,
  }));
  const q = search.trim().toLowerCase();
  const items = [...devs, ...capas].filter((c) =>
    (kindFilter === 'all' || c.kind === kindFilter) &&
    (!q || c.title.toLowerCase().includes(q) || c.ref.toLowerCase().includes(q) || (c.parent_ref ?? '').toLowerCase().includes(q)));
  const byKey = new Map(items.map((c) => [c.key, c]));
  const canDrag = (c: Card) => user?.role !== 'employee' || c.assigned_employee_id === user?.id;
  const loading = devQ.isLoading || capaQ.isLoading;

  const drop = async (col: string) => {
    const key = dragKey;
    setDragKey(null); setOverCol(null);
    if (key == null) return;
    const item = byKey.get(key);
    if (!item || effStatus(item, (item as any)._overdue) === col || busyKey === key) return;
    if (!item.assigned_employee_id && col !== 'Open' && col !== 'Cancelled') {
      notify('Assign an employee first — open the record to pick an assignee before moving it out of Open.', { tone: 'error' });
      return;
    }
    setMoves((m) => ({ ...m, [key]: col }));
    setBusyKey(key);
    try {
      if (item.kind === 'dev') await api.post(`/api/v1/actions/${item.id}/status`, { status: col });
      else await api.patch(`/api/v1/sub-actions/${item.id}`, { status: col });
      await Promise.all([devQ.refetch(), capaQ.refetch()]);
    } catch (e: any) {
      setMoves((m) => { const n = { ...m }; delete n[key]; return n; });
      notify(e.message, { tone: 'error' });
      return;
    } finally {
      setBusyKey(null);
    }
    setMoves((m) => { const n = { ...m }; delete n[key]; return n; });
  };

  const devCount = devs.length;
  const capaCount = capas.length;

  return (
    <div className="space-y-3">
      <div className="flex flex-wrap gap-2 items-center">
        <h1 className="page-title mr-auto">Workflow Board</h1>
        <div className="flex gap-1" role="tablist" aria-label="Card type filter">
          {([['all', `All (${devCount + capaCount})`], ['dev', `Deviations (${devCount})`], ['capa', `CAPAs (${capaCount})`]] as const).map(([k, label]) => (
            <button key={k} type="button" role="tab" aria-selected={kindFilter === k} onClick={() => setKindFilter(k)}
              className={`btn-ghost btn-sm ${kindFilter === k ? '!border-slate-900 font-bold' : ''}`}>{label}</button>
          ))}
        </div>
        <input className="input h-10 text-sm max-w-52" type="search" placeholder="Search cards" aria-label="Search cards"
          value={search} onChange={(e) => setSearch(e.target.value)} />
      </div>
      <p className="hint">Deviations + their CAPAs, side by side. Drag cards between columns to change status{loading ? ' — loading…' : ''}</p>
      <div className="flex gap-3 overflow-x-auto pb-2 snap-x lg:grid lg:overflow-visible md:grid-cols-3 xl:grid-cols-4">
        {COLS.map((c) => {
          const colItems = items.filter((i) => effStatus(i, (i as any)._overdue) === c);
          const active = overCol === c;
          return (
            <section
              key={c}
              aria-label={`${c} cards`}
              onDragOver={(e) => { e.preventDefault(); e.dataTransfer.dropEffect = 'move'; setOverCol(c); }}
              onDragLeave={() => setOverCol((o) => (o === c ? null : o))}
              onDrop={(e) => { e.preventDefault(); drop(c); }}
              className={`card !p-2 min-h-40 min-w-[240px] snap-start lg:min-w-0 transition ${active ? 'ring-2 ring-slate-900' : ''}`}
              style={{ background: 'var(--bg)' }}
            >
              <p className="text-xs font-semibold uppercase text-slate-500 px-1 flex items-center gap-1">
                {c}
                <span className="ml-auto min-w-5 text-center rounded-full bg-slate-200 px-1 text-[11px] font-bold">{colItems.length}</span>
              </p>
              <div className="space-y-2 mt-2">
                {colItems.map((a) => {
                  const draggable = canDrag(a);
                  const dragging = dragKey === a.key;
                  const overdue = (a as any)._overdue;
                  return (
                    <motion.div key={a.key} layout>
                      <div
                        draggable={draggable}
                        aria-grabbed={dragging}
                        onDragStart={(e) => {
                          e.dataTransfer.setData('text/plain', a.key);
                          e.dataTransfer.effectAllowed = 'move';
                          setDragKey(a.key);
                        }}
                        onDragEnd={() => { setDragKey(null); setOverCol(null); }}
                        title={draggable ? 'Drag to another column to change status' : 'Open to change status'}
                        className={`relative block border rounded-lg p-2 pl-3 hover:shadow ${draggable ? 'cursor-grab active:cursor-grabbing' : ''} ${dragging ? 'opacity-50' : ''}`}
                        style={{ background: 'var(--surface)' }}
                      >
                        <span aria-hidden="true"
                          className={`absolute left-0 top-2 bottom-2 w-1 rounded-full ${PRIORITY_BAR[a.priority ?? ''] ?? 'bg-slate-200'}`} />
                        <Link href={a.link}>
                          <span className="flex items-center gap-1">
                            <span className={`badge text-[10px] ${a.kind === 'dev' ? 'bg-blue-100 text-blue-800' : 'bg-purple-100 text-purple-800'}`}>
                              {a.kind === 'dev' ? 'DEV' : 'CAPA'}
                            </span>
                            <span className="font-mono text-[11px] text-slate-500">{a.ref}</span>
                          </span>
                          <p className="text-sm font-medium leading-tight mt-0.5">{a.title}</p>
                          {a.parent_ref && <p className="text-[11px] text-slate-500">of {a.parent_ref}</p>}
                          <span className="flex items-center gap-1.5 mt-1.5">
                            <span className={`text-[11px] px-1.5 py-px rounded ${overdue ? 'bg-red-100 text-red-700 font-semibold' : 'bg-slate-100 text-slate-500'}`}>
                              {a.target_date ? `Due ${formatDate(a.target_date)}` : 'No due date'}
                            </span>
                            <span className="ml-auto inline-flex items-center justify-center w-6 h-6 rounded-full bg-slate-200 text-[10px] font-bold text-slate-600"
                              title={a.assignee_name ?? 'Unassigned'}>
                              {initials(a.assignee_name)}
                            </span>
                          </span>
                        </Link>
                      </div>
                    </motion.div>
                  );
                })}
                {colItems.length === 0 && (
                  <p className={`text-[11px] text-center py-4 rounded border border-dashed ${active ? 'text-slate-700' : 'text-slate-400'}`}>
                    {active ? 'Drop here' : 'No cards'}
                  </p>
                )}
              </div>
            </section>
          );
        })}
      </div>
    </div>
  );
}
