import { useEffect, useState, useMemo } from 'react'
import { useNavigate, useLocation } from '@tanstack/react-router'
import {
  Upload, Search, Building2, GitBranch,
  Clock, TrendingUp, BarChart2, FileX2, X, Settings,
  MoreVertical, Trash2, Share2, Lock, User,
  ChevronDown, FolderOpen,
} from 'lucide-react'
import { useLibraryStore } from '@/store/library-store'
import { useAuth } from '@/auth/AuthContext'
import { supabaseProcessRepo, type ProcessWithUserNames } from '@/persistence/supabase/process-repo'
import { formatCurrency, formatSimulationTimestamp } from '@/lib/format'
import type { Process, Simulation } from '@/domain/types'
import { AppHeader } from '@/components/AppHeader'
import { AppFooter } from '@/components/AppFooter'

// ─── Helpers ──────────────────────────────────────────────────────────────────

function relativeDate(ts: number): string {
  const days = Math.floor((Date.now() - ts) / 86_400_000)
  if (days === 0) return 'hoy'
  if (days === 1) return 'hace 1 día'
  return `hace ${days} días`
}

function tagCloudData(processes: Process[]): Array<{ tag: string; count: number; fontSize: string }> {
  const freq = new Map<string, number>()
  processes.forEach((p) => p.tags.forEach((t) => freq.set(t, (freq.get(t) ?? 0) + 1)))
  const sorted = [...freq.entries()].sort((a, b) => b[1] - a[1]).slice(0, 12)
  if (sorted.length === 0) return []
  const maxCount = sorted[0][1]
  const minCount = sorted[sorted.length - 1][1]
  const range = maxCount - minCount || 1
  return sorted.map(([tag, count]) => {
    const t = (count - minCount) / range
    return { tag, count, fontSize: `${Math.round(10 + t * 3)}px` }
  })
}

function matchesSearch(p: Process, q: string): boolean {
  const lower = q.toLowerCase()
  return p.name.toLowerCase().includes(lower) || p.tags.some((t) => t.includes(lower))
}

function matchesTags(p: Process, activeTags: string[]): boolean {
  return activeTags.every((t) => p.tags.includes(t))
}

// ─── Ownership Badge ──────────────────────────────────────────────────────────

function OwnershipBadge({ process, currentUserId }: { process: Process; currentUserId: string }) {
  const isOwn = process.ownerId === currentUserId
  return (
    <div
      className="flex-shrink-0 flex items-center"
      title={isOwn ? 'Solo vos' : 'De otro consultor'}
    >
      {isOwn
        ? <Lock className="h-3 w-3 text-muted-foreground/60" />
        : <User className="h-3 w-3 text-muted-foreground/60" />
      }
    </div>
  )
}

// ─── Toast ────────────────────────────────────────────────────────────────────

function useToast() {
  const [message, setMessage] = useState<string | null>(null)

  function show(msg: string) {
    setMessage(msg)
    setTimeout(() => setMessage(null), 2800)
  }

  return { message, show }
}

function Toast({ message }: { message: string | null }) {
  if (!message) return null
  return (
    <div
      className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50 px-4 py-2.5 rounded-lg text-[13px] font-medium text-white shadow-lg transition-all"
      style={{ background: '#15803d' }}
    >
      {message}
    </div>
  )
}

// ─── KPI Badge ────────────────────────────────────────────────────────────────

function KpiBadge({ process, simulation }: { process: Process; simulation: Simulation | null | undefined }) {
  if (simulation === undefined) return null // cargando

  if (!simulation) {
    return <span className="text-[11px] italic text-muted-foreground">Sin simular</span>
  }

  if (simulation.resultAutomated) {
    const ahorro = (simulation.result.totalCost - simulation.resultAutomated.totalCost) * process.annualFrequency
    return (
      <div className="text-right">
        <div className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-medium"
          style={{ background: '#f0fdf4', border: '1px solid #86efac', color: '#15803d' }}>
          <TrendingUp className="h-3 w-3" />
          {formatCurrency(ahorro, process.currency)}
        </div>
        <p className="text-[10px] text-muted-foreground mt-0.5">Ahorro anual proyectado</p>
      </div>
    )
  }

  const costoAnual = simulation.result.totalCost * process.annualFrequency
  return (
    <div className="text-right">
      <div className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-medium border border-border bg-secondary text-secondary-foreground">
        <BarChart2 className="h-3 w-3" />
        {formatCurrency(costoAnual, process.currency)}
      </div>
      <p className="text-[10px] text-muted-foreground mt-0.5">Costo anual actual</p>
    </div>
  )
}

// ─── Process Card ─────────────────────────────────────────────────────────────

function ProcessCard({ process, simulation, showGroupChip, groupName, onDelete, currentUserId, currentUserName, onShared }: {
  process: ProcessWithUserNames
  simulation: Simulation | null | undefined
  showGroupChip?: boolean
  groupName?: string
  onDelete?: () => void
  currentUserId: string
  currentUserName: string
  onShared?: () => void
}) {
  const navigate = useNavigate()
  const [menuState, setMenuState] = useState<null | 'menu' | 'confirm'>(null)
  const isOwn = process.ownerId === currentUserId
  const updatedByMe = process.updaterName === currentUserName
  const fullDate = formatSimulationTimestamp(process.updatedAt)

  // Cierra el menú al hacer click fuera de él
  useEffect(() => {
    if (!menuState) return
    function handleDocClick() { setMenuState(null) }
    document.addEventListener('click', handleDocClick)
    return () => document.removeEventListener('click', handleDocClick)
  }, [menuState])

  return (
    <div
      className="flex items-center gap-3 px-4 py-3 rounded-xl border border-border bg-card hover:border-border/80 hover:shadow-sm transition-all cursor-pointer group"
      onClick={() => {
        if (menuState) { setMenuState(null); return }
        navigate({ to: '/workspace/$processId', params: { processId: process.id } })
      }}
    >
      {/* Ícono */}
      <div className="flex-shrink-0 w-9 h-9 rounded-lg flex items-center justify-center"
        style={{ background: '#fff3e6' }}>
        <GitBranch className="h-4 w-4" style={{ color: '#F59845' }} />
      </div>

      {/* Info central */}
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-1.5">
          <p className="text-[13px] font-medium truncate">{process.name || 'Sin nombre'}</p>
          <OwnershipBadge process={process} currentUserId={currentUserId} />
        </div>
        <div className="flex items-center gap-1 mt-0.5" title={`${fullDate.date} a las ${fullDate.time}`}>
          <Clock className="h-3 w-3 text-muted-foreground" />
          <span className="text-[11px] text-muted-foreground">
            Actualizado por {updatedByMe ? 'vos' : process.updaterName} · {relativeDate(process.updatedAt)}
          </span>
        </div>
        {(process.tags.length > 0 || showGroupChip) && (
          <div className="flex flex-wrap gap-1 mt-1">
            {showGroupChip && groupName && (
              <span className="text-[10px] px-2 py-0.5 rounded-full border"
                style={{ background: '#fff3e6', borderColor: '#F59845', color: '#7a3e00' }}>
                {groupName}
              </span>
            )}
            {process.tags.map((tag) => (
              <span key={tag} className="text-[10px] px-2 py-0.5 rounded-full bg-secondary border border-border text-secondary-foreground">
                {tag}
              </span>
            ))}
          </div>
        )}
      </div>

      {/* KPI derecha */}
      <div className="flex-shrink-0 min-w-[90px]">
        <KpiBadge process={process} simulation={simulation} />
      </div>

      {/* Menú de opciones (⋮) — en el flujo flex, a la derecha del KPI */}
      {onDelete && (
        <div
          className="relative flex-shrink-0"
          onClick={(e) => e.stopPropagation()}
        >
          <button
            className={`p-1 rounded hover:bg-secondary text-muted-foreground hover:text-foreground transition-all ${menuState === null ? 'opacity-0 group-hover:opacity-100' : 'opacity-100'}`}
            onClick={(e) => { e.stopPropagation(); setMenuState(menuState === 'menu' ? null : 'menu') }}
            title="Opciones"
          >
            <MoreVertical className="h-3.5 w-3.5" />
          </button>
          {menuState === 'menu' && (
            <div
              className="absolute right-0 top-7 z-20 bg-card border border-border rounded-lg shadow-lg py-1 min-w-[160px]"
              onClick={(e) => e.stopPropagation()}
            >
              {isOwn && (
                <button
                  className="flex items-center gap-2 w-full px-3 py-1.5 text-[12px] text-foreground hover:bg-secondary transition-colors"
                  onClick={async (e) => {
                    e.stopPropagation()
                    await supabaseProcessRepo.setShared(process.id, true)
                    setMenuState(null)
                    onShared?.()
                  }}
                >
                  <Share2 className="h-3.5 w-3.5" />
                  Compartir con equipo
                </button>
              )}
              <button
                className="flex items-center gap-2 w-full px-3 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 transition-colors"
                onClick={(e) => { e.stopPropagation(); setMenuState('confirm') }}
              >
                <Trash2 className="h-3.5 w-3.5" />
                Eliminar
              </button>
            </div>
          )}
          {menuState === 'confirm' && (
            <div
              className="absolute right-0 top-6 z-20 bg-card border border-border rounded-lg shadow-lg p-3 min-w-[170px]"
              onClick={(e) => e.stopPropagation()}
            >
              <p className="text-[12px] font-medium mb-2 text-foreground">¿Eliminar proceso?</p>
              <p className="text-[11px] text-muted-foreground mb-3">Esta acción no se puede deshacer.</p>
              <div className="flex gap-1.5">
                <button
                  className="flex-1 text-[11px] px-2 py-1 rounded font-medium text-white transition-opacity hover:opacity-90"
                  style={{ background: '#ef4444' }}
                  onClick={(e) => { e.stopPropagation(); onDelete(); setMenuState(null) }}
                >
                  Eliminar
                </button>
                <button
                  className="flex-1 text-[11px] px-2 py-1 rounded border border-border text-muted-foreground hover:bg-secondary transition-colors"
                  onClick={(e) => { e.stopPropagation(); setMenuState(null) }}
                >
                  Cancelar
                </button>
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  )
}

// ─── Home View ────────────────────────────────────────────────────────────────

function HomeView({
  onImport,
  ownerFilter,
  currentUserId,
  currentUserName,
  onShared,
}: {
  onImport: () => void
  ownerFilter: 'all' | 'mine'
  currentUserId: string
  currentUserName: string
  onShared: () => void
}) {
  const { groups, processes, isLoading, error, load } = useLibraryStore()
  const { user } = useAuth()
  const [search, setSearch] = useState('')
  const [activeTags, setActiveTags] = useState<string[]>([])

  const visibleProcesses = ownerFilter === 'mine'
    ? processes.filter((p) => p.ownerId === currentUserId)
    : processes

  const cloud = tagCloudData(visibleProcesses)

  const isSearching = search.trim().length > 0 || activeTags.length > 0

  const [collapsedOrgs, setCollapsedOrgs] = useState<Set<string>>(new Set())

  const orgGroups = useMemo(() => {
    const byOrg = new Map<string, { orgId: string; orgName: string; processes: ProcessWithUserNames[] }>()
    for (const p of visibleProcesses) {
      const key = p.orgId ?? '__sin_org'
      const orgName = p.orgName ?? 'Sin organización'
      if (!byOrg.has(key)) byOrg.set(key, { orgId: key, orgName, processes: [] })
      byOrg.get(key)!.processes.push(p)
    }
    return [...byOrg.values()].sort((a, b) => a.orgName.localeCompare(b.orgName))
  }, [visibleProcesses])

  function getAreaGroups(orgProcesses: ProcessWithUserNames[]) {
    const byArea = new Map<string, { areaId: string; areaName: string; processes: ProcessWithUserNames[] }>()
    for (const p of orgProcesses) {
      const key = p.areaId ?? '__sin_area'
      const areaName = p.areaName ?? 'Sin área'
      if (!byArea.has(key)) byArea.set(key, { areaId: key, areaName, processes: [] })
      byArea.get(key)!.processes.push(p)
    }
    return [...byArea.values()].sort((a, b) => {
      if (a.areaId === '__sin_area') return 1
      if (b.areaId === '__sin_area') return -1
      return a.areaName.localeCompare(b.areaName)
    })
  }

  function toggleOrg(orgId: string) {
    setCollapsedOrgs(prev => {
      const next = new Set(prev)
      if (next.has(orgId)) next.delete(orgId)
      else next.add(orgId)
      return next
    })
  }

  const filteredProcesses = isSearching
    ? visibleProcesses.filter((p) => matchesSearch(p, search) && matchesTags(p, activeTags))
    : []

  function toggleTag(tag: string) {
    setActiveTags((prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag])
  }

  // Skeleton mientras carga y aún no hay datos (evita flash de empty state)
  if (isLoading && groups.length === 0 && processes.length === 0) {
    return (
      <div className="space-y-5 animate-pulse">
        <div className="h-4 w-32 bg-slate-100 rounded" />
        <div className="grid gap-2.5" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))' }}>
          {[1, 2, 3].map((i) => (
            <div key={i} className="h-20 rounded-xl bg-slate-100" />
          ))}
        </div>
        <div className="space-y-2">
          {[1, 2].map((i) => (
            <div key={i} className="h-14 rounded-xl bg-slate-100" />
          ))}
        </div>
      </div>
    )
  }

  // Error state: el load() falló o se colgó (timeout) — distinto de "biblioteca vacía"
  if (error && groups.length === 0 && processes.length === 0) {
    return (
      <div className="flex flex-col items-center justify-center py-24 gap-4">
        <Building2 className="h-16 w-16 text-destructive/40" />
        <p className="text-base font-medium">No se pudo cargar la biblioteca</p>
        <p className="text-[13px] text-muted-foreground max-w-sm text-center">{error}</p>
        <button
          onClick={() => load()}
          className="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium text-white transition-opacity hover:opacity-90"
          style={{ background: '#F59845' }}
        >
          Reintentar
        </button>
      </div>
    )
  }

  const isClientRole = user?.platformRole === 'client_editor' || user?.platformRole === 'client_viewer'

  // Empty state: sin grupos ni procesos (ya terminó de cargar)
  if (groups.length === 0 && processes.length === 0) {
    if (isClientRole) {
      return (
        <div className="flex flex-col items-center justify-center py-24 gap-4">
          <Building2 className="h-16 w-16 text-muted-foreground/30" />
          <p className="text-base font-medium">No tenés procesos asignados aún</p>
          <p className="text-[13px] text-muted-foreground">Contactá a tu administrador para que te asigne acceso</p>
        </div>
      )
    }
    return (
      <div className="flex flex-col items-center justify-center py-24 gap-4">
        <Building2 className="h-16 w-16 text-muted-foreground/30" />
        <p className="text-base font-medium">Tu biblioteca está vacía</p>
        <p className="text-[13px] text-muted-foreground">Importá tu primer BPMN para empezar</p>
        <button
          onClick={() => onImport()}
          className="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium text-white transition-opacity hover:opacity-90"
          style={{ background: '#F59845' }}
        >
          <Upload className="h-4 w-4" />
          Importar BPMN
        </button>
      </div>
    )
  }

  return (
    <div className="space-y-5">
      {/* Búsqueda */}
      <div className="relative">
        <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
        <input
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder="Buscar proceso por nombre..."
          className="w-full pl-9 pr-4 py-2 text-sm rounded-lg border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
        />
      </div>

      {/* Resultados de búsqueda */}
      {isSearching && (
        <div className="space-y-2">
          {/* Filtros activos */}
          {activeTags.length > 0 && (
            <div className="flex items-center gap-1.5 flex-wrap">
              <span className="text-[11px] text-muted-foreground">Filtros activos:</span>
              {activeTags.map((tag) => (
                <button
                  key={tag}
                  onClick={() => toggleTag(tag)}
                  className="inline-flex items-center gap-1 text-[11px] px-2 py-0.5 rounded-full border"
                  style={{ background: '#fff3e6', borderColor: '#F59845', color: '#7a3e00' }}
                >
                  {tag} <X className="h-2.5 w-2.5" />
                </button>
              ))}
              <button
                onClick={() => setActiveTags([])}
                className="text-[11px] text-muted-foreground hover:text-foreground"
              >
                Limpiar todo
              </button>
            </div>
          )}
          <p className="text-[11px] text-muted-foreground uppercase tracking-wide font-medium">
            {filteredProcesses.length} resultado{filteredProcesses.length !== 1 ? 's' : ''}
          </p>
          {filteredProcesses.length === 0 && (
            <p className="text-[13px] text-muted-foreground py-4 text-center">Sin resultados para esa búsqueda.</p>
          )}
          {filteredProcesses.map((p) => (
            <ProcessCardWithSim
              key={p.id}
              process={p}
              showGroupChip
              groupName={p.areaName ?? p.orgName ?? undefined}
              currentUserId={currentUserId}
              currentUserName={currentUserName}
              onShared={onShared}
            />
          ))}
        </div>
      )}

      {/* Vista normal — org → área (solo roles internos) */}
      {!isSearching && !isClientRole && (
        <div className="space-y-3" data-testid="groups-header">
          {/* Tag cloud (wow): visible cuando hay >= 3 tags distintos */}
          {cloud.length >= 3 && (
            <div className="flex flex-wrap items-center gap-2">
              <span className="text-[11px] text-muted-foreground shrink-0">Tags:</span>
              {cloud.map(({ tag, fontSize }) => (
                <button
                  key={tag}
                  onClick={() => toggleTag(tag)}
                  className="px-2 py-0.5 rounded-full border transition-all hover:border-[#F59845] hover:bg-[#fff3e6] hover:text-[#7a3e00]"
                  style={{ fontSize, background: 'white', borderColor: 'hsl(var(--border))' }}
                >
                  {tag}
                </button>
              ))}
            </div>
          )}
          {/* Tags simples cuando hay 1-2 */}
          {cloud.length > 0 && cloud.length < 3 && (
            <div className="flex items-center gap-2 flex-wrap">
              <span className="text-[12px] text-muted-foreground">Tags:</span>
              {cloud.map(({ tag }) => (
                <button
                  key={tag}
                  onClick={() => toggleTag(tag)}
                  className="text-[11px] px-2.5 py-0.5 rounded-full border transition-all"
                  style={{ background: 'white', borderColor: 'hsl(var(--border))' }}
                >
                  {tag}
                </button>
              ))}
            </div>
          )}

          {/* Grupos org → área */}
          {orgGroups.map(({ orgId, orgName, processes: orgProcesses }) => {
            const isCollapsed = collapsedOrgs.has(orgId)
            const areaGroups = getAreaGroups(orgProcesses)

            return (
              <div key={orgId} id={`org-section-${orgId}`} className="border border-border rounded-xl overflow-hidden">
                {/* Header de org — colapsable */}
                <button
                  onClick={() => toggleOrg(orgId)}
                  className="w-full flex items-center justify-between px-4 py-3 bg-secondary/40 hover:bg-secondary/60 transition-colors"
                >
                  <div className="flex items-center gap-2">
                    <Building2 className="h-4 w-4 text-muted-foreground" />
                    <span className="text-[13px] font-medium">{orgName}</span>
                    <span className="text-[11px] bg-secondary px-1.5 py-0.5 rounded text-muted-foreground">
                      {orgProcesses.length}
                    </span>
                  </div>
                  <ChevronDown
                    className="h-4 w-4 text-muted-foreground transition-transform duration-200"
                    style={{ transform: isCollapsed ? 'rotate(-90deg)' : 'rotate(0deg)' }}
                  />
                </button>

                {/* Contenido — animado */}
                <div
                  className="transition-all duration-200 overflow-hidden"
                  style={{ maxHeight: isCollapsed ? 0 : '9999px', opacity: isCollapsed ? 0 : 1 }}
                >
                  <div className="p-3 space-y-3">
                    {areaGroups.map(({ areaId, areaName, processes: areaProcesses }) => (
                      <div key={areaId}>
                        {/* Sub-header de área: visible si hay >1 área o si el área tiene nombre */}
                        {(areaGroups.length > 1 || areaId !== '__sin_area') && (
                          <p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground mb-2 flex items-center gap-1.5">
                            <FolderOpen className="h-3 w-3" />
                            {areaName}
                            <span className="normal-case tracking-normal font-normal">
                              · {areaProcesses.length}
                            </span>
                          </p>
                        )}
                        <div className="space-y-2">
                          {areaProcesses.map((p) => (
                            <ProcessCardWithSim
                              key={p.id}
                              process={p}
                              currentUserId={currentUserId}
                              currentUserName={currentUserName}
                              onShared={onShared}
                            />
                          ))}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            )
          })}

          {/* Empty state: admin sin procesos */}
          {orgGroups.length === 0 && (
            <div className="flex flex-col items-center justify-center py-16 gap-3">
              <Building2 className="h-12 w-12 text-muted-foreground/30" />
              <p className="text-[13px] font-medium text-secondary-foreground">
                Tu biblioteca está vacía
              </p>
              <p className="text-[13px] text-muted-foreground">
                Importá tu primer BPMN para empezar
              </p>
              <button
                onClick={() => onImport()}
                className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium text-white"
                style={{ background: '#F59845' }}
              >
                <Upload className="h-4 w-4" />
                Importar BPMN
              </button>
            </div>
          )}
        </div>
      )}

      {/* Vista cliente: lista plana de procesos (sin grupos, RLS garantiza que solo ven los suyos) */}
      {!isSearching && isClientRole && (
        <div className="space-y-2">
          {visibleProcesses.map((p) => (
            <ProcessCardWithSim
              key={p.id}
              process={p}
              currentUserId={currentUserId}
              currentUserName={currentUserName}
              onShared={onShared}
            />
          ))}
        </div>
      )}
    </div>
  )
}

// ─── ProcessCardWithSim (carga simulación lazy) ───────────────────────────────

function ProcessCardWithSim({ process, showGroupChip, groupName, currentUserId, currentUserName, onShared }: {
  process: ProcessWithUserNames
  showGroupChip?: boolean
  groupName?: string
  currentUserId: string
  currentUserName: string
  onShared: () => void
}) {
  const { getLatestSimulation, deleteProcess } = useLibraryStore()
  const [simulation, setSimulation] = useState<Simulation | null | undefined>(undefined)

  useEffect(() => {
    let cancelled = false
    getLatestSimulation(process.id).then((sim) => {
      if (!cancelled) setSimulation(sim ?? null)
    })
    return () => { cancelled = true }
  }, [process.id, getLatestSimulation])

  return (
    <ProcessCard
      process={process}
      simulation={simulation}
      showGroupChip={showGroupChip}
      groupName={groupName}
      onDelete={() => deleteProcess(process.id)}
      currentUserId={currentUserId}
      currentUserName={currentUserName}
      onShared={onShared}
    />
  )
}

// ─── Group View ───────────────────────────────────────────────────────────────

function GroupView({
  groupId,
  onBack,
  currentUserId,
  currentUserName,
  ownerFilter,
  onShared,
}: {
  groupId: string | null
  onBack: () => void
  currentUserId: string
  currentUserName: string
  ownerFilter: 'all' | 'mine'
  onShared: () => void
}) {
  const { groups, processes, settings } = useLibraryStore()
  const [search, setSearch] = useState('')

  const group = groupId ? groups.find((g) => g.id === groupId) : null
  const groupName = group?.name ?? `Procesos sin ${settings.groupLabel.toLowerCase()}`

  const baseProcesses = ownerFilter === 'mine'
    ? processes.filter((p) => p.ownerId === currentUserId)
    : processes

  const groupProcesses = baseProcesses
    .filter((p) => groupId === null ? p.groupId == null : p.groupId === groupId)
    .filter((p) => matchesSearch(p, search))

  return (
    <div className="space-y-5">
      {/* Breadcrumb */}
      <div className="flex items-center gap-2">
        <button
          onClick={onBack}
          className="text-[13px] font-medium hover:opacity-80 transition-opacity"
          style={{ color: '#F59845' }}
        >
          ← Biblioteca
        </button>
        <span className="text-muted-foreground text-[13px]">/</span>
        <span className="text-[13px] font-medium">{groupName}</span>
      </div>
      <p className="text-[12px] text-muted-foreground -mt-3">
        {groupProcesses.length} proceso{groupProcesses.length !== 1 ? 's' : ''}
      </p>

      {/* Búsqueda */}
      <div className="relative">
        <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
        <input
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          placeholder={`Buscar en este ${settings.groupLabel.toLowerCase()}...`}
          className="w-full pl-9 pr-4 py-2 text-sm rounded-lg border border-border bg-background focus:outline-none focus:ring-1 focus:ring-primary"
        />
      </div>

      {/* Empty state */}
      {groupProcesses.length === 0 && !search && (
        <div className="flex flex-col items-center justify-center py-16 gap-3">
          <FileX2 className="h-12 w-12 text-muted-foreground/30" />
          <p className="text-[13px] font-medium text-secondary-foreground">
            No hay procesos en este {settings.groupLabel.toLowerCase()}.
          </p>
          <p className="text-[13px] text-muted-foreground">Importá un BPMN para comenzar.</p>
        </div>
      )}

      {/* Lista de procesos */}
      <div className="space-y-2">
        {groupProcesses.map((p) => (
          <ProcessCardWithSim
            key={p.id}
            process={p}
            currentUserId={currentUserId}
            currentUserName={currentUserName}
            onShared={onShared}
          />
        ))}
      </div>
    </div>
  )
}

// ─── LibraryPage ──────────────────────────────────────────────────────────────

export function LibraryPage() {
  const navigate = useNavigate()
  const { load, processes, isLoading } = useLibraryStore()
  const { user, isProfileLoaded } = useAuth()
  const [view, setView] = useState<'home' | 'group'>('home')
  const [activeGroupId, setActiveGroupId] = useState<string | null>(null)
  const [transitioning, setTransitioning] = useState(false)
  const [ownerFilter, setOwnerFilter] = useState<'all' | 'mine'>('all')
  const { message: toastMessage, show: showToast } = useToast()

  const location = useLocation()
  const orgParam = useMemo(
    () => new URLSearchParams(location.search).get('org') ?? undefined,
    [location.search]
  )

  useEffect(() => {
    if (!user) return // no fetchear hasta tener usuario confirmado (evita race condition con sesión Supabase)
    load()
  }, [load, user?.id])

  // Scroll a la sección del org si venimos del workspace
  useEffect(() => {
    if (!orgParam || isLoading || processes.length === 0) return
    requestAnimationFrame(() => {
      const el = document.getElementById(`org-section-${orgParam}`)
      el?.scrollIntoView({ behavior: 'smooth', block: 'start' })
    })
  }, [orgParam, isLoading, processes.length])

  function navigateHome() {
    setTransitioning(true)
    setTimeout(() => {
      setView('home')
      setActiveGroupId(null)
      setTransitioning(false)
    }, 150)
  }

  function handleImport() {
    navigate({ to: '/import' })
  }

  // Esperar a que syncProfileFromDB complete antes de renderizar UI rol-dependiente.
  // Evita el flash donde 'guest' se muestra como platform_admin durante la ventana de sync.
  if (!user || !isProfileLoaded) {
    return (
      <div className="min-h-screen bg-background">
        <AppHeader />
        <div className="max-w-4xl mx-auto px-6 py-8">
          <div className="space-y-5 animate-pulse">
            <div className="h-4 w-32 bg-slate-100 rounded" />
            <div className="grid gap-2.5" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))' }}>
              {[1, 2, 3].map((i) => <div key={i} className="h-20 rounded-xl bg-slate-100" />)}
            </div>
            <div className="space-y-2">
              {[1, 2].map((i) => <div key={i} className="h-14 rounded-xl bg-slate-100" />)}
            </div>
          </div>
        </div>
      </div>
    )
  }

  const currentUserId = user.id
  const currentUserName = user.name
  const isClientRole = user.platformRole === 'client_editor' || user.platformRole === 'client_viewer'
  const orgCount = new Set(processes.map(p => p.orgId).filter(Boolean)).size

  return (
    <div className="min-h-screen bg-background">
      <AppHeader />
      <div className="max-w-4xl mx-auto px-6 py-8">
        {/* Header */}
        <div className="flex items-start justify-between mb-6">
          <div>
            <h1 className="text-[18px] font-medium">Biblioteca de procesos</h1>
            <p className="text-[12px] text-muted-foreground mt-0.5">
              {isClientRole
                ? `${processes.length} proceso${processes.length !== 1 ? 's' : ''}`
                : `${processes.length} proceso${processes.length !== 1 ? 's' : ''} · ${orgCount} cliente${orgCount !== 1 ? 's' : ''}`
              }
            </p>
          </div>
          <div className="flex items-center gap-2">
            {/* Toggle Todos / Míos */}
            <div className="flex rounded-lg border border-border overflow-hidden text-[12px]">
              <button
                className="px-3 py-1.5 font-medium transition-colors"
                style={ownerFilter === 'all'
                  ? { background: '#F59845', color: 'white' }
                  : { background: 'transparent', color: 'hsl(var(--muted-foreground))' }
                }
                onClick={() => setOwnerFilter('all')}
              >
                Todos
              </button>
              <button
                className="px-3 py-1.5 font-medium transition-colors border-l border-border"
                style={ownerFilter === 'mine'
                  ? { background: '#F59845', color: 'white' }
                  : { background: 'transparent', color: 'hsl(var(--muted-foreground))' }
                }
                onClick={() => setOwnerFilter('mine')}
              >
                Míos
              </button>
            </div>

            {!isClientRole && (
              <button
                onClick={() => navigate({ to: '/settings' })}
                className="p-2 rounded-lg text-muted-foreground hover:text-foreground hover:bg-secondary transition-colors"
                title="Configuración"
              >
                <Settings className="h-4 w-4" />
              </button>
            )}
            {!isClientRole && (
              <button
                onClick={handleImport}
                className="flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium text-white transition-opacity hover:opacity-90"
                style={{ background: '#F59845' }}
              >
                <Upload className="h-4 w-4" />
                Importar BPMN
              </button>
            )}
          </div>
        </div>

        {/* Contenido — sin spinner bloqueante: skeleton dentro de HomeView */}
        <div
          className="transition-all duration-150"
          style={{ opacity: transitioning ? 0 : 1, transform: transitioning ? 'translateY(6px)' : 'translateY(0)' }}
        >
          {view === 'home' ? (
            <HomeView
              onImport={handleImport}
              ownerFilter={ownerFilter}
              currentUserId={currentUserId}
              currentUserName={currentUserName}
              onShared={() => showToast('Proceso compartido con el equipo')}
            />
          ) : (
            <GroupView
              groupId={activeGroupId}
              onBack={navigateHome}
              currentUserId={currentUserId}
              currentUserName={currentUserName}
              ownerFilter={ownerFilter}
              onShared={() => showToast('Proceso compartido con el equipo')}
            />
          )}
        </div>
        <AppFooter />
      </div>

      <Toast message={toastMessage} />
    </div>
  )
}
