import { useEffect, useRef, useState, useCallback, useMemo, useDeferredValue } from 'react'
import { useParams, useNavigate } from '@tanstack/react-router'
import {
  Loader2, BarChart3, Play, AlertTriangle, AlertCircle,
  PanelRightClose, PanelRightOpen, ArrowLeft, GitMerge, MousePointer2,
  Check, Pencil
} from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from '@/components/ui/tooltip'
import { Separator } from '@/components/ui/separator'
import { BpmnCanvas, type BpmnElementCategory } from './BpmnCanvas'
import { ActivityPanel } from './ActivityPanel'
import { GatewayPanel, isXorSumValid } from './GatewayPanel'
import { ResourcesPanel } from './ResourcesPanel'
import { GlobalSettingsPanel } from './GlobalSettingsPanel'
import { WorkspaceSkeleton } from './WorkspaceSkeleton'
import { useProcessStore } from '@/store/process-store'
import { useSimulationStore } from '@/store/simulation-store'
import { useSimulate } from '../simulation/useSimulate'
import { useLibraryStore } from '@/store/library-store'
import { useAuth } from '@/auth/AuthContext'
import { AppHeader } from '@/components/AppHeader'
import { ErrorBoundary } from '@/components/ErrorBoundary'

type SelectedCategory = 'activity' | 'gateway' | null

export function WorkspacePage() {
  const { processId } = useParams({ from: '/workspace/$processId' })
  const navigate = useNavigate()
  const { currentProcess, activities, isLoading, error, loadProcess, gateways, updateProcess } = useProcessStore()
  const { isRunning, resultActual, error: simError, selectActivity, loadLatestForProcess, lastPersistedExecutedAt } = useSimulationStore()
  const { simulate } = useSimulate()
  const { user } = useAuth()

  const [sidebarOpen, setSidebarOpen] = useState(true)
  const [selectedElementId, setSelectedElementId] = useState<string | null>(null)
  const [selectedElementName, setSelectedElementName] = useState<string>('')
  const [selectedCategory, setSelectedCategory] = useState<SelectedCategory>(null)
  const [activeTab, setActiveTab] = useState('elemento')

  // Estado para edición inline del header
  const [editingField, setEditingField] = useState<'name' | 'client' | null>(null)
  const [editValue, setEditValue] = useState('')
  const [savedField, setSavedField] = useState<'name' | 'client' | null>(null)
  const savedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  // Tags chip input
  const [tagInput, setTagInput] = useState('')
  const [showTagSuggestions, setShowTagSuggestions] = useState(false)
  const getAllTags = useLibraryStore((state) => state.getAllTags)

  useEffect(() => { loadProcess(processId) }, [processId, loadProcess])

  // Cargar el último executedAt persistido para comparar contra updatedAt (indicador stale).
  // Depende de currentProcess?.id (no del objeto) a propósito: evita re-disparar el efecto
  // en cada edición de campos del proceso, solo cuando cambia de proceso.
  useEffect(() => {
    if (currentProcess) loadLatestForProcess(currentProcess.id)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentProcess?.id, loadLatestForProcess])

  // client_viewer no puede editar — redirigir al reporte
  useEffect(() => {
    if (user?.platformRole === 'client_viewer') {
      void navigate({ to: '/report/$processId', params: { processId } })
    }
  }, [user, processId, navigate])

  // orgName viene directamente del proceso cargado via JOIN en getById (sin fetch separado)

  // Validación XOR: todos los gateways exclusivos deben sumar 1.0
  const xorValidation = useMemo(() => {
    const invalidIds = gateways
      .filter((gw) => gw.gatewayType === 'exclusive' && !isXorSumValid(gw))
      .map((gw) => gw.bpmnElementId)
    return { valid: invalidIds.length === 0, invalidIds }
  }, [gateways])

  const canSimulate = !isRunning && xorValidation.valid

  // Hay cambios sin simular cuando updatedAt supera al executedAt de la última simulación persistida
  const isStale = Boolean(
    currentProcess &&
    currentProcess.updatedAt > (lastPersistedExecutedAt ?? 0)
  )

  // IDs de actividades marcadas como automatizables — alimenta los overlays del canvas.
  // useDeferredValue evita re-renders en cascada mientras el usuario edita el panel.
  const automatableElementIds = useMemo(
    () => activities.filter((a) => a.automatable).map((a) => a.bpmnElementId),
    [activities]
  )
  const deferredAutomatableIds = useDeferredValue(automatableElementIds)

  const handleElementClick = useCallback((
    elementId: string,
    elementName: string,
    category: BpmnElementCategory
  ) => {
    if (category === 'other') return
    setSelectedElementId(elementId)
    setSelectedElementName(elementName)
    setSelectedCategory(category)
    selectActivity(category === 'activity' ? elementId : null)
    setActiveTab('elemento')
    if (!sidebarOpen) setSidebarOpen(true)
  }, [selectActivity, sidebarOpen])

  function clearSelection() {
    setSelectedElementId(null)
    setSelectedElementName('')
    setSelectedCategory(null)
    selectActivity(null)
  }

  async function saveField(field: 'name' | 'client') {
    if (field === 'name') {
      const trimmed = editValue.trim()
      if (trimmed && trimmed !== currentProcess?.name) {
        await updateProcess({ name: trimmed }, user!.id)
      }
    } else {
      const trimmed = editValue.trim()
      if (trimmed !== (currentProcess?.clientName ?? '')) {
        await updateProcess({ clientName: trimmed }, user!.id)
      }
    }
    setEditingField(null)
    setSavedField(field)
    if (savedTimerRef.current) clearTimeout(savedTimerRef.current)
    savedTimerRef.current = setTimeout(() => setSavedField(null), 1500)
  }

  function addTag(raw: string) {
    const normalized = raw.trim().toLowerCase()
    if (!normalized) return
    const current = currentProcess?.tags ?? []
    if (current.some((t) => t === normalized)) return
    updateProcess({ tags: [...current, normalized] }, user!.id)
    setTagInput('')
    setShowTagSuggestions(false)
  }

  function removeTag(tag: string) {
    const current = currentProcess?.tags ?? []
    updateProcess({ tags: current.filter((t) => t !== tag) }, user!.id)
  }

  function handleTagKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === 'Enter') { e.preventDefault(); if (tagInput.trim()) addTag(tagInput) }
    if (e.key === 'Escape') { setTagInput(''); setShowTagSuggestions(false) }
  }

  async function handleSimulate() {
    if (!canSimulate) return
    const simResult = await simulate()
    if (simResult) navigate({ to: '/report/$processId', params: { processId } })
  }



  // isLoading manda siempre, incluso si currentProcess todavía tiene el proceso
  // anterior en el store (navegación directa entre dos workspaces distintos).
  if (isLoading || user?.platformRole === 'client_viewer') {
    return <WorkspaceSkeleton />
  }

  if (error || !currentProcess) {
    return (
      <div className="h-screen flex flex-col items-center justify-center gap-4">
        <AlertCircle className="h-8 w-8 text-muted-foreground" />
        <p className="text-sm text-muted-foreground max-w-sm text-center">
          {error ?? 'No se pudo cargar el proceso. Revisá tu conexión.'}
        </p>
        <div className="flex gap-2">
          <Button variant="outline" onClick={() => loadProcess(processId)}>
            Reintentar
          </Button>
          <Button variant="ghost" onClick={() => navigate({ to: '/' })}>
            Volver a la biblioteca
          </Button>
        </div>
      </div>
    )
  }

  // client_viewer ya fue redirigido antes de este punto; solo verificamos client_editor aquí
  const isClientRole = user?.platformRole === 'client_editor'
  const backLabel = isClientRole
    ? 'Procesos'
    : currentProcess.orgName ?? 'Biblioteca'

  function handleBack() {
    void navigate({
      to: '/library',
      search: { org: currentProcess?.orgId ?? undefined },
    })
  }

  // Label del tab "elemento" según lo seleccionado
  const elementTabLabel = selectedCategory === 'gateway' ? 'Gateway' : 'Actividad'
  const elementTabIcon = selectedCategory === 'gateway'
    ? <GitMerge className="h-3 w-3 mr-1" />
    : <MousePointer2 className="h-3 w-3 mr-1" />

  return (
    <TooltipProvider>
      <div className="h-screen flex flex-col bg-slate-100 overflow-hidden">
        <AppHeader />

        {/* ── Topbar ─────────────────────────────────────────────────── */}
        <header className="min-h-12 bg-white border-b border-slate-200 flex items-center px-3 gap-3 shrink-0 z-10">
          <Button
            variant="ghost"
            size="sm"
            className="gap-1 text-xs text-slate-500 h-8 px-2 shrink-0"
            onClick={handleBack}
          >
            <ArrowLeft className="h-3.5 w-3.5" />
            {backLabel}
          </Button>

          <Separator orientation="vertical" className="h-5" />

          <div className="flex-1 min-w-0">

            {/* Nombre del proceso — editable inline */}
            {editingField === 'name' ? (
              <input
                autoFocus
                className="text-sm font-semibold text-slate-800 bg-transparent border-b border-[#F59845] outline-none w-full"
                value={editValue}
                onChange={(e) => setEditValue(e.target.value)}
                onBlur={() => saveField('name')}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') { e.preventDefault(); saveField('name') }
                  if (e.key === 'Escape') setEditingField(null)
                }}
              />
            ) : (
              <div
                className="flex items-center gap-1 group cursor-text"
                onClick={() => { setEditValue(currentProcess.name); setEditingField('name') }}
              >
                <p className="text-sm font-semibold text-slate-800 truncate">{currentProcess.name}</p>
                {savedField === 'name'
                  ? <Check className="h-3.5 w-3.5 text-[#F59845] shrink-0" />
                  : <Pencil className="h-3 w-3 text-slate-300 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity" />
                }
              </div>
            )}

            {/* Área — display de solo lectura (editable desde el panel de configuración) */}
            {currentProcess.areaName && (
              <p className="text-xs text-slate-400 truncate">{currentProcess.areaName}</p>
            )}

            {/* Tags — chips removibles + input inline */}
            {(() => {
              const processTags = currentProcess.tags ?? []
              const suggestions = getAllTags()
                .filter((t) => t.includes(tagInput.toLowerCase()) && !processTags.includes(t))
                .slice(0, 6)
              return (
                <div className="flex flex-wrap items-center gap-1 mt-0.5">
                  {processTags.map((tag) => (
                    <span
                      key={tag}
                      className="inline-flex items-center gap-0.5 text-[10px] px-1.5 py-0.5 rounded-full bg-secondary border border-border text-secondary-foreground"
                    >
                      {tag}
                      <button
                        type="button"
                        onClick={() => removeTag(tag)}
                        className="ml-0.5 text-muted-foreground hover:text-foreground leading-none"
                      >
                        ×
                      </button>
                    </span>
                  ))}
                  <div className="relative">
                    <input
                      type="text"
                      value={tagInput}
                      onChange={(e) => { setTagInput(e.target.value); setShowTagSuggestions(true) }}
                      onKeyDown={handleTagKeyDown}
                      onFocus={() => setShowTagSuggestions(true)}
                      onBlur={() => setTimeout(() => setShowTagSuggestions(false), 150)}
                      placeholder="Agregar tag..."
                      className="text-xs bg-transparent border-b border-muted outline-none w-24 placeholder:text-muted-foreground/50"
                    />
                    {showTagSuggestions && suggestions.length > 0 && (
                      <div className="absolute top-full left-0 mt-1 bg-background border border-border rounded-md shadow-sm z-50 min-w-[120px]">
                        {suggestions.map((s) => (
                          <button
                            key={s}
                            type="button"
                            className="w-full text-left px-2 py-1 text-[11px] hover:bg-secondary transition-colors"
                            onMouseDown={(e) => { e.preventDefault(); addTag(s) }}
                          >
                            {s}
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                </div>
              )
            })()}

          </div>

          {/* Errores de simulación */}
          {simError && (
            <div className="flex items-center gap-1.5 text-destructive text-xs bg-destructive/10 px-2 py-1 rounded">
              <AlertTriangle className="h-3.5 w-3.5 shrink-0" />
              {simError}
            </div>
          )}

          {/* Advertencia de XOR inválido */}
          {!xorValidation.valid && (
            <Tooltip>
              <TooltipTrigger asChild>
                <div className="flex items-center gap-1.5 text-amber-700 text-xs bg-amber-50 border border-amber-200 px-2 py-1 rounded cursor-help">
                  <AlertTriangle className="h-3.5 w-3.5 shrink-0" />
                  {xorValidation.invalidIds.length} gateway{xorValidation.invalidIds.length > 1 ? 's' : ''} con probabilidades inválidas
                </div>
              </TooltipTrigger>
              <TooltipContent side="bottom" className="max-w-60 text-xs">
                <p className="font-semibold mb-1">Gateways XOR que no suman 100%:</p>
                {xorValidation.invalidIds.map((id) => (
                  <p key={id} className="font-mono">• {id}</p>
                ))}
                <p className="mt-1 text-slate-300">Ajustá las probabilidades para habilitar la simulación</p>
              </TooltipContent>
            </Tooltip>
          )}

          {/* Ver reporte si ya hay simulación */}
          {resultActual && (
            <Button
              variant="outline"
              size="sm"
              className="h-8 text-xs gap-1.5 text-primary border-primary/30"
              onClick={() => navigate({ to: '/report/$processId', params: { processId } })}
            >
              <BarChart3 className="h-3.5 w-3.5" />
              Ver reporte
            </Button>
          )}

          {/* Indicador stale */}
          {isStale && (
            <div className="flex items-center gap-1 px-2 py-1 rounded text-[11px] font-medium"
              style={{ background: '#fff3e6', border: '1px solid #F59845', color: '#7a3e00' }}>
              <AlertCircle className="h-3 w-3 shrink-0" />
              Hay cambios sin simular
            </div>
          )}

          {/* Simular */}
          <Tooltip>
            <TooltipTrigger asChild>
              <span>
                <Button
                  size="sm"
                  className="h-8 text-xs gap-1.5"
                  onClick={handleSimulate}
                  disabled={!canSimulate}
                >
                  {isRunning
                    ? <><Loader2 className="h-3.5 w-3.5 animate-spin" />Simulando…</>
                    : <><Play className="h-3.5 w-3.5" />Simular</>
                  }
                </Button>
              </span>
            </TooltipTrigger>
            {!xorValidation.valid && (
              <TooltipContent side="bottom" className="text-xs">
                Corregí las probabilidades de los gateways XOR primero
              </TooltipContent>
            )}
          </Tooltip>

          <Separator orientation="vertical" className="h-5" />

          <Tooltip>
            <TooltipTrigger asChild>
              <Button
                variant="ghost"
                size="icon"
                className="h-8 w-8"
                onClick={() => setSidebarOpen((v) => !v)}
              >
                {sidebarOpen ? <PanelRightClose className="h-4 w-4" /> : <PanelRightOpen className="h-4 w-4" />}
              </Button>
            </TooltipTrigger>
            <TooltipContent>{sidebarOpen ? 'Cerrar panel' : 'Abrir panel'}</TooltipContent>
          </Tooltip>
        </header>

        {/* ── Main ───────────────────────────────────────────────────── */}
        <div className="flex-1 flex overflow-hidden relative">

          {/* Canvas BPMN */}
          <div className="flex-1 relative overflow-hidden bpmn-container">
            <BpmnCanvas
              xml={currentProcess.bpmnXml}
              onElementClick={handleElementClick}
              selectedElementId={selectedElementId}
              automatableElementIds={deferredAutomatableIds}
              className="absolute inset-0"
            />

            {/* Chip de elemento seleccionado */}
            {selectedElementId && (
              <div className="absolute top-3 left-3 bg-white/90 backdrop-blur-sm border border-slate-200 rounded-lg px-3 py-1.5 shadow-sm flex items-center gap-2 max-w-xs">
                <div className={`w-2 h-2 rounded-full shrink-0 ${selectedCategory === 'gateway' ? 'bg-amber-500' : 'bg-primary'}`} />
                <span className="text-xs font-medium text-slate-700 truncate">{selectedElementName || selectedElementId}</span>
                <button onClick={clearSelection} className="ml-1 text-slate-400 hover:text-slate-600 shrink-0">×</button>
              </div>
            )}

            {/* Hint inicial */}
            {!selectedElementId && (
              <div className="absolute bottom-4 left-1/2 -translate-x-1/2 bg-white/80 backdrop-blur-sm border border-slate-200 rounded-full px-4 py-2 shadow-sm">
                <p className="text-xs text-slate-500">Hacé click en una tarea o gateway para configurarlo</p>
              </div>
            )}
          </div>

          {/* Panel lateral */}
          <div className={`
            shrink-0 bg-white border-l border-slate-200 flex flex-col overflow-hidden
            transition-all duration-300 ease-in-out
            ${sidebarOpen ? 'w-72' : 'w-0'}
          `}>
            {sidebarOpen && (
              <Tabs value={activeTab} onValueChange={setActiveTab} className="flex flex-col h-full">
                <TabsList className="shrink-0 mx-3 mt-3 grid grid-cols-3 w-auto">
                  <TabsTrigger value="elemento" className="text-xs flex items-center">
                    {elementTabIcon}{elementTabLabel}
                  </TabsTrigger>
                  <TabsTrigger value="recursos" className="text-xs">Recursos</TabsTrigger>
                  <TabsTrigger value="global" className="text-xs">Global</TabsTrigger>
                </TabsList>

                <TabsContent value="elemento" className="flex-1 overflow-hidden mt-0 data-[state=active]:flex data-[state=active]:flex-col">
                  {selectedCategory === 'gateway'
                    ? <GatewayPanel selectedElementId={selectedElementId} />
                    : <ActivityPanel selectedElementId={selectedElementId} />
                  }
                </TabsContent>

                <TabsContent value="recursos" className="flex-1 overflow-hidden mt-0 data-[state=active]:flex data-[state=active]:flex-col">
                  <ResourcesPanel />
                </TabsContent>

                <TabsContent value="global" className="flex-1 overflow-hidden mt-0 data-[state=active]:flex data-[state=active]:flex-col">
                  <GlobalSettingsPanel />
                </TabsContent>
              </Tabs>
            )}
          </div>

          {/* Toggle flotante cuando sidebar cerrado */}
          {!sidebarOpen && (
            <button
              onClick={() => setSidebarOpen(true)}
              className="absolute right-0 top-1/2 -translate-y-1/2 bg-white border border-slate-200 border-r-0 rounded-l-lg p-1.5 shadow-md hover:bg-slate-50 z-20"
            >
              <PanelRightOpen className="h-4 w-4 text-slate-500" />
            </button>
          )}
        </div>
      </div>
    </TooltipProvider>
  )
}

export function WorkspacePageWithBoundary() {
  return (
    <ErrorBoundary>
      <WorkspacePage />
    </ErrorBoundary>
  )
}
