'use client'

import React, { useState, useEffect, useCallback } from 'react'
import Header from '@/components/layout/Header'
import { useSession } from 'next-auth/react'
import {
  ChevronRightIcon, PlusIcon, PencilSquareIcon, TrashIcon,
  XMarkIcon, CheckIcon, PaperClipIcon, ArrowUpTrayIcon,
} from '@heroicons/react/24/outline'

// ─── Types ────────────────────────────────────────────────────────────────────

type BL = { id: number; name: string; slug: string }
type Node = {
  id: number; name: string; description: string | null
  type: 'MACROPROCESO' | 'PROCESO' | 'SUBPROCESO'
  order: number; parentId: number | null; businessLineId: number | null
  businessLine: BL | null
  _count: { documents: number; children: number }
}
type TreeNode = Node & { children: TreeNode[] }

type ActivityDoc = { id: number; name: string; url: string; size: number | null }
type Activity = {
  id: number; name: string; processNodeId: number
  processNode: { id: number; name: string }
  processType: string | null; projectAssoc: string | null; areaValue: string | null
  leader: string | null; responsible: string | null; support: string | null
  priority: string; complexity: string | null; observations: string | null
  outputType: string | null; gantt: string | null; status: string; order: number
  documents: ActivityDoc[]
}

// ─── Constants ────────────────────────────────────────────────────────────────

const TYPE_LABEL = { MACROPROCESO: 'Macroproceso', PROCESO: 'Proceso', SUBPROCESO: 'Subproceso' }
const TYPE_COLOR = {
  MACROPROCESO: 'bg-blue-100 text-blue-700',
  PROCESO: 'bg-indigo-100 text-indigo-700',
  SUBPROCESO: 'bg-gray-100 text-gray-600',
}
const TYPE_DOT = { MACROPROCESO: 'bg-blue-500', PROCESO: 'bg-indigo-400', SUBPROCESO: 'bg-gray-400' }
const TYPE_CHILD: Record<string, string> = { MACROPROCESO: 'PROCESO', PROCESO: 'SUBPROCESO' }

const PRIORITY_BADGE: Record<string, string> = {
  ALTA: 'bg-red-100 text-red-700',
  MEDIA: 'bg-yellow-100 text-yellow-700',
  BAJA: 'bg-green-100 text-green-700',
}
const STATUS_BADGE: Record<string, string> = {
  PENDIENTE: 'bg-gray-100 text-gray-600',
  EN_PROCESO: 'bg-blue-100 text-blue-700',
  COMPLETADO: 'bg-green-100 text-green-700',
  BLOQUEADO: 'bg-red-100 text-red-600',
}
const STATUS_LABEL: Record<string, string> = {
  PENDIENTE: 'Pendiente',
  EN_PROCESO: 'En proceso',
  COMPLETADO: 'Completado',
  BLOQUEADO: 'Bloqueado',
}
const STATUS_CYCLE = ['PENDIENTE', 'EN_PROCESO', 'COMPLETADO', 'BLOQUEADO']
const OUTPUT_TYPES = ['Procedimiento', 'Registro', 'Metodología', 'Proyecto', 'Hito', 'Definición', 'Otro']
const PROCESS_TYPES = ['Estratégico', 'Core', 'Apoyo']

// ─── Tree helpers ─────────────────────────────────────────────────────────────

function buildTree(nodes: Node[]): TreeNode[] {
  const map = new Map<number, TreeNode>()
  nodes.forEach(n => map.set(n.id, { ...n, children: [] }))
  const roots: TreeNode[] = []
  map.forEach(n => {
    if (n.parentId && map.has(n.parentId)) map.get(n.parentId)!.children.push(n)
    else roots.push(n)
  })
  return roots
}

function TreeItem({ node, selectedId, onSelect, level = 0 }: {
  node: TreeNode; selectedId: number | null; onSelect: (n: Node) => void; level?: number
}) {
  const [open, setOpen] = useState(level < 2)
  const hasChildren = node.children.length > 0
  const isSelected = selectedId === node.id

  return (
    <div>
      <button
        onClick={() => { setOpen(!open); onSelect(node) }}
        className={`w-full flex items-center gap-2 py-2 pr-3 text-sm rounded-lg text-left transition-colors ${
          isSelected ? 'bg-green-50 text-green-800 font-medium' : 'text-gray-700 hover:bg-gray-50'
        }`}
        style={{ paddingLeft: `${level * 16 + 10}px` }}
      >
        <ChevronRightIcon className={`w-3.5 h-3.5 flex-shrink-0 text-gray-400 transition-transform ${
          hasChildren ? (open ? 'rotate-90' : '') : 'opacity-0'
        }`} />
        <span className={`w-2 h-2 rounded-full flex-shrink-0 ${TYPE_DOT[node.type]}`} />
        <span className="truncate flex-1">{node.name}</span>
        {node._count.documents > 0 && (
          <span className="text-xs text-gray-400 flex-shrink-0">{node._count.documents}</span>
        )}
      </button>
      {open && hasChildren && node.children.map(c => (
        <TreeItem key={c.id} node={c} selectedId={selectedId} onSelect={onSelect} level={level + 1} />
      ))}
    </div>
  )
}

// ─── Activity row ─────────────────────────────────────────────────────────────

function ActivityRow({ act, canEdit, onEdit, onDelete, onStatusChange }: {
  act: Activity; canEdit: boolean
  onEdit: (a: Activity) => void
  onDelete: (a: Activity) => void
  onStatusChange: (a: Activity, status: string) => void
}) {
  const nextStatus = (cur: string) => STATUS_CYCLE[(STATUS_CYCLE.indexOf(cur) + 1) % STATUS_CYCLE.length]

  return (
    <tr className="hover:bg-gray-50 group border-b border-gray-50 last:border-0">
      <td className="py-2.5 px-3 max-w-[220px]">
        <p className="text-sm text-gray-800 line-clamp-2">{act.name}</p>
        {act.areaValue && <p className="text-xs text-gray-400 mt-0.5">{act.areaValue}</p>}
      </td>
      <td className="py-2.5 px-3 text-xs text-gray-500 whitespace-nowrap">{act.responsible || '—'}</td>
      <td className="py-2.5 px-3 text-xs text-gray-500 whitespace-nowrap">{act.leader || '—'}</td>
      <td className="py-2.5 px-3">
        <span className={`px-2 py-0.5 rounded-full text-xs font-medium whitespace-nowrap ${PRIORITY_BADGE[act.priority] ?? 'bg-gray-100 text-gray-600'}`}>
          {act.priority}
        </span>
      </td>
      <td className="py-2.5 px-3">
        {canEdit ? (
          <button
            onClick={() => onStatusChange(act, nextStatus(act.status))}
            title="Clic para avanzar estado"
            className={`px-2 py-0.5 rounded-full text-xs font-medium whitespace-nowrap hover:opacity-75 ${STATUS_BADGE[act.status] ?? 'bg-gray-100 text-gray-600'}`}
          >
            {STATUS_LABEL[act.status] ?? act.status}
          </button>
        ) : (
          <span className={`px-2 py-0.5 rounded-full text-xs font-medium whitespace-nowrap ${STATUS_BADGE[act.status] ?? ''}`}>
            {STATUS_LABEL[act.status] ?? act.status}
          </span>
        )}
      </td>
      <td className="py-2.5 px-3 text-xs text-gray-500 whitespace-nowrap">{act.outputType || '—'}</td>
      <td className="py-2.5 px-3 text-xs text-gray-400 whitespace-nowrap">{act.gantt || '—'}</td>
      <td className="py-2.5 px-3">
        {act.documents.length > 0 ? (
          <span className="flex items-center gap-1 text-xs text-gray-400">
            <PaperClipIcon className="w-3.5 h-3.5" />{act.documents.length}
          </span>
        ) : <span className="text-xs text-gray-300">—</span>}
      </td>
      {canEdit && (
        <td className="py-2.5 px-3">
          <div className="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
            <button onClick={() => onEdit(act)} className="p-1 rounded hover:bg-gray-200 text-gray-500">
              <PencilSquareIcon className="w-3.5 h-3.5" />
            </button>
            <button onClick={() => onDelete(act)} className="p-1 rounded hover:bg-red-50 text-red-400">
              <TrashIcon className="w-3.5 h-3.5" />
            </button>
          </div>
        </td>
      )}
    </tr>
  )
}

// ─── Default forms ────────────────────────────────────────────────────────────

const emptyForm = { name: '', description: '', type: 'MACROPROCESO', parentId: '', businessLineId: '', order: '0' }
const emptyActForm = {
  name: '', processType: '', projectAssoc: '', areaValue: '',
  leader: '', responsible: '', support: '',
  priority: 'ALTA', complexity: '', observations: '',
  outputType: '', gantt: '', status: 'PENDIENTE', order: '0',
}

// ─── Input helper ─────────────────────────────────────────────────────────────

function Field({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div>
      <label className="block text-xs font-medium text-gray-500 mb-1.5">{label}</label>
      {children}
    </div>
  )
}
const cls = 'w-full border border-gray-200 rounded-lg px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-green-500'

// ─── Page ─────────────────────────────────────────────────────────────────────

export default function MapaProcesosPage() {
  const { data: session } = useSession()
  const canEdit = ['SUPER_ADMIN', 'ADMIN', 'EDITOR'].includes((session?.user as { role?: string })?.role ?? '')

  // Process tree
  const [nodes, setNodes] = useState<Node[]>([])
  const [bls, setBls] = useState<BL[]>([])
  const [loading, setLoading] = useState(true)
  const [selected, setSelected] = useState<Node | null>(null)
  const [filterBl, setFilterBl] = useState('')
  const [modal, setModal] = useState<'new' | 'edit' | null>(null)
  const [form, setForm] = useState(emptyForm)
  const [saving, setSaving] = useState(false)
  const [saveError, setSaveError] = useState('')
  const [deleting, setDeleting] = useState(false)
  const [confirmDelete, setConfirmDelete] = useState(false)

  // Activities
  const [activities, setActivities] = useState<Activity[]>([])
  const [actsLoading, setActsLoading] = useState(false)
  const [actModal, setActModal] = useState<'new' | 'edit' | null>(null)
  const [editingAct, setEditingAct] = useState<Activity | null>(null)
  const [actForm, setActForm] = useState(emptyActForm)
  const [actSaving, setActSaving] = useState(false)
  const [actError, setActError] = useState('')
  const [actTab, setActTab] = useState<'datos' | 'archivos'>('datos')
  const [confirmDelAct, setConfirmDelAct] = useState<Activity | null>(null)
  const [uploadingDoc, setUploadingDoc] = useState(false)

  // ── Load tree ──────────────────────────────────────────────────────────────

  const load = useCallback(async () => {
    setLoading(true)
    const res = await fetch('/api/procesos')
    const data = await res.json()
    setNodes(data.nodes)
    setBls(data.businessLines)
    setLoading(false)
  }, [])

  useEffect(() => { load() }, [load])

  const filtered = filterBl
    ? nodes.filter(n => n.businessLineId === parseInt(filterBl))
    : nodes
  const tree = buildTree(filtered)

  // ── Load activities ────────────────────────────────────────────────────────

  const loadActivities = useCallback(async (nodeId: number) => {
    setActsLoading(true)
    try {
      const res = await fetch(`/api/actividades?nodeId=${nodeId}&includeDescendants=true`)
      if (res.ok) {
        const data = await res.json()
        setActivities(Array.isArray(data) ? data : [])
      } else {
        setActivities([])
      }
    } catch {
      setActivities([])
    }
    setActsLoading(false)
  }, [])

  useEffect(() => {
    if (selected) loadActivities(selected.id)
    else setActivities([])
  }, [selected, loadActivities])

  // ── Process node CRUD ──────────────────────────────────────────────────────

  function openNew(parent?: Node) {
    const childType = parent ? (TYPE_CHILD[parent.type] ?? 'SUBPROCESO') : 'MACROPROCESO'
    setForm({ ...emptyForm, type: childType, parentId: parent ? String(parent.id) : '', businessLineId: parent?.businessLineId ? String(parent.businessLineId) : '' })
    setSaveError(''); setModal('new')
  }

  function openEdit() {
    if (!selected) return
    setForm({ name: selected.name, description: selected.description ?? '', type: selected.type, parentId: selected.parentId ? String(selected.parentId) : '', businessLineId: selected.businessLineId ? String(selected.businessLineId) : '', order: String(selected.order) })
    setModal('edit')
  }

  async function save() {
    setSaving(true); setSaveError('')
    const url = modal === 'edit' ? `/api/procesos/${selected!.id}` : '/api/procesos'
    try {
      const res = await fetch(url, { method: modal === 'edit' ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(form) })
      if (res.ok) { setModal(null); load() }
      else { const d = await res.json().catch(() => ({})); setSaveError(d.error ?? `Error ${res.status}`) }
    } catch { setSaveError('Error de conexión') }
    finally { setSaving(false) }
  }

  async function deleteNode() {
    if (!selected) return
    setDeleting(true)
    await fetch(`/api/procesos/${selected.id}`, { method: 'DELETE' })
    setDeleting(false); setSelected(null); setConfirmDelete(false); load()
  }

  // ── Activity CRUD ──────────────────────────────────────────────────────────

  function openNewAct() {
    setEditingAct(null); setActForm(emptyActForm); setActError(''); setActTab('datos'); setActModal('new')
  }

  function openEditAct(act: Activity) {
    setEditingAct(act)
    setActForm({
      name: act.name, processType: act.processType ?? '', projectAssoc: act.projectAssoc ?? '',
      areaValue: act.areaValue ?? '', leader: act.leader ?? '', responsible: act.responsible ?? '',
      support: act.support ?? '', priority: act.priority, complexity: act.complexity ?? '',
      observations: act.observations ?? '', outputType: act.outputType ?? '',
      gantt: act.gantt ?? '', status: act.status, order: String(act.order),
    })
    setActError(''); setActTab('datos'); setActModal('edit')
  }

  async function saveAct() {
    if (!selected) return
    setActSaving(true); setActError('')
    const url = actModal === 'edit' ? `/api/actividades/${editingAct!.id}` : '/api/actividades'
    try {
      const res = await fetch(url, {
        method: actModal === 'edit' ? 'PUT' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ...actForm, processNodeId: selected.id, order: parseInt(actForm.order) || 0 }),
      })
      if (res.ok) {
        const saved: Activity = await res.json()
        await loadActivities(selected.id)
        if (actModal === 'new') {
          setEditingAct(saved); setActTab('archivos'); setActModal('edit')
        } else {
          setActModal(null)
        }
      } else {
        const d = await res.json().catch(() => ({})); setActError(d.error ?? `Error ${res.status}`)
      }
    } catch { setActError('Error de conexión') }
    finally { setActSaving(false) }
  }

  async function deleteAct(act: Activity) {
    await fetch(`/api/actividades/${act.id}`, { method: 'DELETE' })
    setConfirmDelAct(null)
    if (selected) loadActivities(selected.id)
  }

  async function changeStatus(act: Activity, status: string) {
    await fetch(`/api/actividades/${act.id}`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ status }),
    })
    if (selected) loadActivities(selected.id)
  }

  async function uploadDoc(e: React.ChangeEvent<HTMLInputElement>) {
    if (!e.target.files?.[0] || !editingAct) return
    setUploadingDoc(true)
    const fd = new FormData()
    fd.append('file', e.target.files[0])
    const uploadRes = await fetch('/api/upload', { method: 'POST', body: fd })
    const { url, name, size } = await uploadRes.json()
    await fetch(`/api/actividades/${editingAct.id}/docs`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ url, name, size }),
    })
    const fresh = await fetch(`/api/actividades/${editingAct.id}`).then(r => r.json())
    setEditingAct(fresh)
    if (selected) loadActivities(selected.id)
    setUploadingDoc(false)
    e.target.value = ''
  }

  async function deleteDoc(docId: number) {
    if (!editingAct) return
    await fetch(`/api/actividades/${editingAct.id}/docs/${docId}`, { method: 'DELETE' })
    const fresh = await fetch(`/api/actividades/${editingAct.id}`).then(r => r.json())
    setEditingAct(fresh)
    if (selected) loadActivities(selected.id)
  }

  // ── Group activities by node ───────────────────────────────────────────────

  const nodeGroups = activities.reduce<Map<number, { name: string; acts: Activity[] }>>(
    (map, act) => {
      if (!map.has(act.processNodeId)) map.set(act.processNodeId, { name: act.processNode.name, acts: [] })
      map.get(act.processNodeId)!.acts.push(act)
      return map
    },
    new Map()
  )
  const nodeGroupList = Array.from(nodeGroups.values())
  const multipleNodes = nodeGroupList.length > 1

  // ── Render ─────────────────────────────────────────────────────────────────

  return (
    <div>
      <Header title="Mapa de Procesos" />
      <div className="flex h-[calc(100vh-65px)]">

        {/* LEFT — tree */}
        <div className="w-72 flex-shrink-0 bg-white border-r border-gray-200 flex flex-col">
          <div className="p-3 border-b border-gray-100 space-y-2">
            <select value={filterBl} onChange={e => setFilterBl(e.target.value)} className="w-full text-xs border border-gray-200 rounded-lg px-2.5 py-1.5 outline-none focus:ring-2 focus:ring-green-500">
              <option value="">Todas las líneas</option>
              {bls.map(b => <option key={b.id} value={b.id}>{b.name}</option>)}
            </select>
            {canEdit && (
              <button onClick={() => openNew()} className="w-full flex items-center justify-center gap-1.5 bg-green-600 hover:bg-green-700 text-white text-xs font-medium px-3 py-1.5 rounded-lg">
                <PlusIcon className="w-3.5 h-3.5" /> Macroproceso
              </button>
            )}
          </div>
          <div className="flex-1 overflow-y-auto p-2">
            {loading ? (
              <p className="text-xs text-gray-400 p-3">Cargando...</p>
            ) : tree.length === 0 ? (
              <p className="text-xs text-gray-400 p-3">Sin procesos registrados.</p>
            ) : (
              tree.map(n => <TreeItem key={n.id} node={n} selectedId={selected?.id ?? null} onSelect={setSelected} />)
            )}
          </div>
        </div>

        {/* RIGHT — detail + activities */}
        <div className="flex-1 overflow-y-auto">
          {!selected ? (
            <div className="flex flex-col items-center justify-center py-32 text-gray-300">
              <p className="text-sm">Selecciona un proceso del árbol</p>
            </div>
          ) : (
            <div>
              {/* Node header */}
              <div className="px-6 pt-5 pb-4 border-b border-gray-100">
                <div className="flex items-start justify-between gap-4">
                  <div className="min-w-0">
                    <span className={`inline-block px-2.5 py-0.5 rounded-full text-xs font-medium mb-1.5 ${TYPE_COLOR[selected.type]}`}>
                      {TYPE_LABEL[selected.type]}
                    </span>
                    <h2 className="text-xl font-semibold text-gray-800 truncate">{selected.name}</h2>
                    <div className="flex items-center gap-3 mt-0.5">
                      {selected.businessLine && <p className="text-xs text-gray-400">Línea: {selected.businessLine.name}</p>}
                      <p className="text-xs text-gray-400">{selected._count.children} sub-nodos · {activities.length} actividades</p>
                    </div>
                    {selected.description && (
                      <p className="text-sm text-gray-500 mt-1.5 line-clamp-2 max-w-2xl">{selected.description}</p>
                    )}
                  </div>
                  {canEdit && (
                    <div className="flex gap-2 flex-shrink-0">
                      <button onClick={openEdit} className="flex items-center gap-1.5 px-3 py-1.5 text-xs border border-gray-200 rounded-lg text-gray-600 hover:bg-gray-50">
                        <PencilSquareIcon className="w-3.5 h-3.5" /> Editar
                      </button>
                      {selected.type !== 'SUBPROCESO' && (
                        <button onClick={() => openNew(selected)} className="flex items-center gap-1.5 px-3 py-1.5 text-xs bg-green-50 text-green-700 border border-green-200 rounded-lg hover:bg-green-100">
                          <PlusIcon className="w-3.5 h-3.5" /> {TYPE_CHILD[selected.type] === 'PROCESO' ? 'Proceso' : 'Subproceso'}
                        </button>
                      )}
                      <button onClick={() => setConfirmDelete(true)} className="flex items-center gap-1.5 px-3 py-1.5 text-xs border border-red-200 text-red-600 rounded-lg hover:bg-red-50">
                        <TrashIcon className="w-3.5 h-3.5" /> Eliminar
                      </button>
                    </div>
                  )}
                </div>
              </div>

              {/* Activities */}
              <div className="px-6 py-4">
                <div className="flex items-center justify-between mb-4">
                  <h3 className="font-semibold text-gray-700 text-sm">
                    Actividades críticas
                    {activities.length > 0 && (
                      <span className="ml-2 px-2 py-0.5 bg-gray-100 text-gray-500 rounded-full text-xs font-normal">
                        {activities.length}
                      </span>
                    )}
                  </h3>
                  {canEdit && (
                    <button onClick={openNewAct} className="flex items-center gap-1.5 bg-green-600 hover:bg-green-700 text-white text-xs font-medium px-3 py-1.5 rounded-lg">
                      <PlusIcon className="w-3.5 h-3.5" /> Nueva actividad
                    </button>
                  )}
                </div>

                {actsLoading ? (
                  <p className="text-xs text-gray-400">Cargando actividades...</p>
                ) : activities.length === 0 ? (
                  <div className="flex flex-col items-center justify-center py-12 text-gray-300 border-2 border-dashed border-gray-100 rounded-xl">
                    <p className="text-sm">Sin actividades registradas</p>
                    {canEdit && <p className="text-xs mt-1">Haz clic en &quot;Nueva actividad&quot; para comenzar</p>}
                  </div>
                ) : (
                  <div className="bg-white border border-gray-100 rounded-xl overflow-x-auto">
                    <table className="w-full text-left min-w-max">
                      <thead className="bg-gray-50 border-b border-gray-100">
                        <tr>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Actividad</th>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Responsable</th>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Líder</th>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Prior.</th>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Estado avance</th>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Tipo doc.</th>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Gantt</th>
                          <th className="py-2.5 px-3 text-xs font-medium text-gray-500">Arch.</th>
                          {canEdit && <th className="py-2.5 px-3 w-14" />}
                        </tr>
                      </thead>
                      <tbody>
                        {nodeGroupList.map(({ name: nodeName, acts }, gi) => (
                          <React.Fragment key={gi}>
                            {multipleNodes && (
                              <tr className="bg-indigo-50">
                                <td colSpan={canEdit ? 9 : 8} className="py-1.5 px-3 text-xs font-semibold text-indigo-600">
                                  {nodeName}
                                </td>
                              </tr>
                            )}
                            {acts.map(act => (
                              <ActivityRow
                                key={act.id}
                                act={act}
                                canEdit={canEdit}
                                onEdit={openEditAct}
                                onDelete={setConfirmDelAct}
                                onStatusChange={changeStatus}
                              />
                            ))}
                          </React.Fragment>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </div>
            </div>
          )}
        </div>
      </div>

      {/* ── MODAL: proceso ── */}
      {modal && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-xl shadow-2xl w-full max-w-lg">
            <div className="flex items-center justify-between p-5 border-b border-gray-100">
              <h3 className="font-semibold text-gray-800">{modal === 'new' ? `Nuevo ${TYPE_LABEL[form.type as keyof typeof TYPE_LABEL]}` : 'Editar proceso'}</h3>
              <button onClick={() => setModal(null)}><XMarkIcon className="w-5 h-5 text-gray-400 hover:text-gray-600" /></button>
            </div>
            <div className="p-5 space-y-4">
              <Field label="Nombre *">
                <input value={form.name} onChange={e => setForm(f => ({ ...f, name: e.target.value }))} className={cls} placeholder="Nombre del proceso" />
              </Field>
              <Field label="Descripción">
                <textarea value={form.description} onChange={e => setForm(f => ({ ...f, description: e.target.value }))} rows={3} className={`${cls} resize-none`} />
              </Field>
              {modal === 'new' && (
                <Field label="Tipo">
                  <select value={form.type} onChange={e => setForm(f => ({ ...f, type: e.target.value }))} className={cls}>
                    <option value="MACROPROCESO">Macroproceso</option>
                    <option value="PROCESO">Proceso</option>
                    <option value="SUBPROCESO">Subproceso</option>
                  </select>
                </Field>
              )}
              <div className="grid grid-cols-2 gap-4">
                <Field label="Línea de negocio">
                  <select value={form.businessLineId} onChange={e => setForm(f => ({ ...f, businessLineId: e.target.value }))} className={cls}>
                    <option value="">Corporativo</option>
                    {bls.map(b => <option key={b.id} value={b.id}>{b.name}</option>)}
                  </select>
                </Field>
                <Field label="Orden">
                  <input type="number" value={form.order} onChange={e => setForm(f => ({ ...f, order: e.target.value }))} className={cls} min="0" />
                </Field>
              </div>
            </div>
            <div className="p-5 border-t border-gray-100 flex items-center justify-between">
              {saveError ? <p className="text-xs text-red-500">{saveError}</p> : <span />}
              <div className="flex gap-3">
                <button onClick={() => setModal(null)} className="px-4 py-2 text-sm text-gray-600">Cancelar</button>
                <button onClick={save} disabled={saving || !form.name} className="flex items-center gap-1.5 px-4 py-2 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-60 font-medium">
                  <CheckIcon className="w-4 h-4" />{saving ? 'Guardando...' : 'Guardar'}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ── MODAL: actividad ── */}
      {actModal && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-xl shadow-2xl w-full max-w-2xl flex flex-col max-h-[90vh]">
            <div className="flex items-center justify-between p-5 border-b border-gray-100 flex-shrink-0">
              <h3 className="font-semibold text-gray-800">{actModal === 'new' ? 'Nueva actividad crítica' : 'Editar actividad'}</h3>
              <button onClick={() => setActModal(null)}><XMarkIcon className="w-5 h-5 text-gray-400 hover:text-gray-600" /></button>
            </div>

            {/* Tabs */}
            <div className="flex border-b border-gray-100 flex-shrink-0">
              <button onClick={() => setActTab('datos')} className={`px-5 py-2.5 text-sm font-medium border-b-2 transition-colors ${actTab === 'datos' ? 'border-green-600 text-green-700' : 'border-transparent text-gray-500 hover:text-gray-700'}`}>
                Datos
              </button>
              <button
                onClick={() => setActTab('archivos')}
                disabled={actModal === 'new'}
                className={`px-5 py-2.5 text-sm font-medium border-b-2 transition-colors disabled:opacity-40 disabled:cursor-not-allowed ${actTab === 'archivos' ? 'border-green-600 text-green-700' : 'border-transparent text-gray-500 hover:text-gray-700'}`}
              >
                Archivos {editingAct && editingAct.documents.length > 0 && `(${editingAct.documents.length})`}
              </button>
            </div>

            {actTab === 'datos' ? (
              <div className="p-5 space-y-4 overflow-y-auto flex-1">
                <Field label="Actividad crítica *">
                  <input value={actForm.name} onChange={e => setActForm(f => ({ ...f, name: e.target.value }))} className={cls} placeholder="Nombre de la actividad" />
                </Field>
                <div className="grid grid-cols-3 gap-4">
                  <Field label="Tipo de proceso">
                    <select value={actForm.processType} onChange={e => setActForm(f => ({ ...f, processType: e.target.value }))} className={cls}>
                      <option value="">—</option>
                      {PROCESS_TYPES.map(t => <option key={t} value={t}>{t}</option>)}
                    </select>
                  </Field>
                  <Field label="Proyecto asociado">
                    <input value={actForm.projectAssoc} onChange={e => setActForm(f => ({ ...f, projectAssoc: e.target.value }))} className={cls} placeholder="ej. Ecosistema Digital" />
                  </Field>
                  <Field label="Área / Cadena de valor">
                    <input value={actForm.areaValue} onChange={e => setActForm(f => ({ ...f, areaValue: e.target.value }))} className={cls} placeholder="ej. Dirección" />
                  </Field>
                </div>
                <div className="grid grid-cols-3 gap-4">
                  <Field label="Líder proyecto">
                    <input value={actForm.leader} onChange={e => setActForm(f => ({ ...f, leader: e.target.value }))} className={cls} />
                  </Field>
                  <Field label="Responsable">
                    <input value={actForm.responsible} onChange={e => setActForm(f => ({ ...f, responsible: e.target.value }))} className={cls} />
                  </Field>
                  <Field label="Apoyo">
                    <input value={actForm.support} onChange={e => setActForm(f => ({ ...f, support: e.target.value }))} className={cls} />
                  </Field>
                </div>
                <div className="grid grid-cols-4 gap-4">
                  <Field label="Prioridad">
                    <select value={actForm.priority} onChange={e => setActForm(f => ({ ...f, priority: e.target.value }))} className={cls}>
                      <option value="ALTA">Alta</option>
                      <option value="MEDIA">Media</option>
                      <option value="BAJA">Baja</option>
                    </select>
                  </Field>
                  <Field label="Complejidad">
                    <select value={actForm.complexity} onChange={e => setActForm(f => ({ ...f, complexity: e.target.value }))} className={cls}>
                      <option value="">—</option>
                      <option value="ALTA">Alta</option>
                      <option value="MEDIA">Media</option>
                      <option value="BAJA">Baja</option>
                    </select>
                  </Field>
                  <Field label="Estado avance">
                    <select value={actForm.status} onChange={e => setActForm(f => ({ ...f, status: e.target.value }))} className={cls}>
                      <option value="PENDIENTE">Pendiente</option>
                      <option value="EN_PROCESO">En proceso</option>
                      <option value="COMPLETADO">Completado</option>
                      <option value="BLOQUEADO">Bloqueado</option>
                    </select>
                  </Field>
                  <Field label="Tipo doc. esperado">
                    <select value={actForm.outputType} onChange={e => setActForm(f => ({ ...f, outputType: e.target.value }))} className={cls}>
                      <option value="">—</option>
                      {OUTPUT_TYPES.map(t => <option key={t} value={t}>{t}</option>)}
                    </select>
                  </Field>
                </div>
                <div className="grid grid-cols-2 gap-4">
                  <Field label="Gantt / Fecha">
                    <input value={actForm.gantt} onChange={e => setActForm(f => ({ ...f, gantt: e.target.value }))} className={cls} placeholder="ej. Q3 2026, Continuo, Enero..." />
                  </Field>
                  <Field label="Orden">
                    <input type="number" value={actForm.order} onChange={e => setActForm(f => ({ ...f, order: e.target.value }))} className={cls} min="0" />
                  </Field>
                </div>
                <Field label="Observaciones">
                  <textarea value={actForm.observations} onChange={e => setActForm(f => ({ ...f, observations: e.target.value }))} rows={3} className={`${cls} resize-none`} placeholder="Notas adicionales..." />
                </Field>
              </div>
            ) : (
              /* Archivos tab */
              <div className="p-5 space-y-4 overflow-y-auto flex-1">
                <label className={`flex flex-col items-center gap-2 p-6 border-2 border-dashed rounded-xl cursor-pointer transition-colors ${uploadingDoc ? 'border-green-300 bg-green-50 cursor-wait' : 'border-gray-200 hover:border-green-300 hover:bg-green-50/50'}`}>
                  <ArrowUpTrayIcon className={`w-8 h-8 ${uploadingDoc ? 'text-green-500 animate-bounce' : 'text-gray-300'}`} />
                  <span className="text-sm text-gray-500">{uploadingDoc ? 'Subiendo archivo...' : 'Haz clic o arrastra un archivo aquí'}</span>
                  <span className="text-xs text-gray-400">PDF, Word, Excel, imágenes — máx. 20 MB</span>
                  <input type="file" className="hidden" onChange={uploadDoc} disabled={uploadingDoc} />
                </label>

                {editingAct && editingAct.documents.length > 0 ? (
                  <ul className="space-y-2">
                    {editingAct.documents.map(doc => (
                      <li key={doc.id} className="flex items-center gap-3 p-3 bg-gray-50 rounded-lg group/doc">
                        <PaperClipIcon className="w-4 h-4 text-gray-400 flex-shrink-0" />
                        <a href={doc.url} target="_blank" rel="noopener noreferrer" className="flex-1 text-sm text-blue-600 hover:underline truncate">
                          {doc.name}
                        </a>
                        {doc.size != null && <span className="text-xs text-gray-400 flex-shrink-0">{(doc.size / 1024).toFixed(0)} KB</span>}
                        <button onClick={() => deleteDoc(doc.id)} className="p-1 rounded opacity-0 group-hover/doc:opacity-100 hover:bg-red-50 text-red-400 flex-shrink-0 transition-opacity">
                          <TrashIcon className="w-3.5 h-3.5" />
                        </button>
                      </li>
                    ))}
                  </ul>
                ) : (
                  <p className="text-xs text-gray-400 text-center py-4">Sin archivos adjuntos</p>
                )}
              </div>
            )}

            <div className="p-5 border-t border-gray-100 flex items-center justify-between flex-shrink-0">
              {actError ? <p className="text-xs text-red-500">{actError}</p> : <span />}
              <div className="flex gap-3">
                <button onClick={() => setActModal(null)} className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800">Cerrar</button>
                {actTab === 'datos' && (
                  <button onClick={saveAct} disabled={actSaving || !actForm.name} className="flex items-center gap-1.5 px-4 py-2 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-60 font-medium">
                    <CheckIcon className="w-4 h-4" />{actSaving ? 'Guardando...' : actModal === 'new' ? 'Crear y adjuntar archivos' : 'Guardar'}
                  </button>
                )}
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ── CONFIRM: eliminar proceso ── */}
      {confirmDelete && selected && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-xl shadow-2xl w-full max-w-sm p-6">
            <h3 className="font-semibold text-gray-800 mb-2">Eliminar proceso</h3>
            <p className="text-sm text-gray-500 mb-1">¿Eliminar <strong>{selected.name}</strong>?</p>
            {selected._count.children > 0 && (
              <p className="text-xs text-red-500 mb-1">⚠ Se eliminarán los {selected._count.children} sub-nodos y sus actividades.</p>
            )}
            <div className="flex justify-end gap-3 mt-5">
              <button onClick={() => setConfirmDelete(false)} className="px-4 py-2 text-sm text-gray-600">Cancelar</button>
              <button onClick={deleteNode} disabled={deleting} className="px-4 py-2 text-sm bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-60">
                {deleting ? 'Eliminando...' : 'Eliminar'}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* ── CONFIRM: eliminar actividad ── */}
      {confirmDelAct && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
          <div className="bg-white rounded-xl shadow-2xl w-full max-w-sm p-6">
            <h3 className="font-semibold text-gray-800 mb-2">Eliminar actividad</h3>
            <p className="text-sm text-gray-500 mb-5">¿Eliminar <strong>{confirmDelAct.name}</strong>? Se perderán los archivos adjuntos.</p>
            <div className="flex justify-end gap-3">
              <button onClick={() => setConfirmDelAct(null)} className="px-4 py-2 text-sm text-gray-600">Cancelar</button>
              <button onClick={() => deleteAct(confirmDelAct)} className="px-4 py-2 text-sm bg-red-600 text-white rounded-lg hover:bg-red-700">
                Eliminar
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}
