/**
 * TaxonomyPage – Gestione della Tassonomia di Classificazione Multi-livello (Feature N2).
 *
 * Struttura gerarchica:
 *   Livello 0 (Radice) = Ambito (Area Aziendale)   — es. "Legale", "Commerciale"
 *   Livello 1           = Processo                  — es. "Contratti", "Contenzioso"
 *   Livello 2 (Foglia)  = Classificazione            — es. "NDA", "Ricorso", "Fattura"
 *
 * Le classificazioni vengono poi assegnate ai messaggi tramite:
 *   - Widget tassonomia nel dettaglio messaggio (selezione manuale)
 *   - Regole di smistamento con azione "apply_taxonomy" (automatica)
 */

import { useState } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import {
  ChevronRight,
  ChevronDown,
  Plus,
  Pencil,
  Trash2,
  Tags,
  Info,
  X,
} from 'lucide-react'
import toast from 'react-hot-toast'
import { Button } from '@/components/ui/Button'
import { Input } from '@/components/ui/Input'
import { Label } from '@/components/ui/Label'
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/Dialog'
import { labelsApi } from '@/api/labels.api'
import type { LabelTreeResponse } from '@/types/api.types'
import { getErrorMessage } from '@/api/client'
import { cn } from '@/lib/utils'

// ─── Livelli della tassonomia ─────────────────────────────────────────────────

const LEVEL_LABELS = ['Ambito', 'Processo', 'Classificazione']
const LEVEL_COLORS = [
  'bg-blue-100 text-blue-800 border-blue-200',
  'bg-purple-100 text-purple-800 border-purple-200',
  'bg-green-100 text-green-800 border-green-200',
]
const LEVEL_BG = [
  'border-l-2 border-blue-400',
  'border-l-2 border-purple-400 ml-6',
  'border-l-2 border-green-400 ml-12',
]

// ─── Calcola la profondita' di un nodo nell'albero ────────────────────────────

function getNodeDepth(node: LabelTreeResponse): number {
  if (!node.parent_id) return 0
  return -1 // verrà calcolato nel contesto dell'albero
}

// ─── Componente nodo dell'albero ──────────────────────────────────────────────

interface TreeNodeProps {
  node: LabelTreeResponse
  depth: number
  onAddChild: (parent: LabelTreeResponse, depth: number) => void
  onEdit: (node: LabelTreeResponse, depth: number) => void
  onDelete: (node: LabelTreeResponse) => void
}

function TreeNode({ node, depth, onAddChild, onEdit, onDelete }: TreeNodeProps) {
  const [expanded, setExpanded] = useState(true)
  const hasChildren = node.children.length > 0
  const levelLabel = LEVEL_LABELS[depth] ?? `Livello ${depth}`
  const levelColor = LEVEL_COLORS[depth] ?? 'bg-gray-100 text-gray-700 border-gray-200'
  const levelBg = LEVEL_BG[depth] ?? 'border-l-2 border-gray-400 ml-16'

  return (
    <div className={cn(levelBg, 'pl-3 py-0.5')}>
      <div className="flex items-center gap-2 py-2 px-2 rounded-lg hover:bg-muted/40 group">
        {/* Espandi/comprimi */}
        {hasChildren ? (
          <button
            type="button"
            onClick={() => setExpanded((v) => !v)}
            className="p-0.5 rounded hover:bg-muted text-muted-foreground"
          >
            {expanded ? (
              <ChevronDown className="h-3.5 w-3.5" />
            ) : (
              <ChevronRight className="h-3.5 w-3.5" />
            )}
          </button>
        ) : (
          <span className="w-5" />
        )}

        {/* Pallino colore */}
        {node.color && (
          <span
            className="h-3.5 w-3.5 rounded-full flex-shrink-0 border"
            style={{ backgroundColor: node.color }}
          />
        )}

        {/* Nome */}
        <span className="flex-1 text-sm font-medium">{node.name}</span>

        {/* Badge livello */}
        <span className={cn('text-xs px-2 py-0.5 rounded-full border font-medium', levelColor)}>
          {levelLabel}
        </span>

        {/* Descrizione (tooltip) */}
        {node.description && (
          <span title={node.description} className="text-muted-foreground cursor-help">
            <Info className="h-3.5 w-3.5" />
          </span>
        )}

        {/* Azioni — visibili solo al hover */}
        <div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
          {depth < 2 && (
            <Button
              variant="ghost"
              size="icon"
              className="h-7 w-7"
              title={`Aggiungi ${LEVEL_LABELS[depth + 1] ?? 'sottonodo'}`}
              onClick={() => onAddChild(node, depth + 1)}
            >
              <Plus className="h-3.5 w-3.5 text-primary" />
            </Button>
          )}
          <Button
            variant="ghost"
            size="icon"
            className="h-7 w-7"
            title="Modifica"
            onClick={() => onEdit(node, depth)}
          >
            <Pencil className="h-3.5 w-3.5 text-muted-foreground" />
          </Button>
          <Button
            variant="ghost"
            size="icon"
            className="h-7 w-7"
            title="Elimina"
            onClick={() => onDelete(node)}
          >
            <Trash2 className="h-3.5 w-3.5 text-destructive" />
          </Button>
        </div>
      </div>

      {/* Figli */}
      {expanded && hasChildren && (
        <div className="mt-0.5">
          {node.children.map((child) => (
            <TreeNode
              key={child.id}
              node={child}
              depth={depth + 1}
              onAddChild={onAddChild}
              onEdit={onEdit}
              onDelete={onDelete}
            />
          ))}
        </div>
      )}
    </div>
  )
}

// ─── Pagina principale ────────────────────────────────────────────────────────

export function TaxonomyPage() {
  const queryClient = useQueryClient()

  // Stato form
  const [showForm, setShowForm] = useState(false)
  const [formName, setFormName] = useState('')
  const [formColor, setFormColor] = useState('')
  const [formDescription, setFormDescription] = useState('')
  const [formParentId, setFormParentId] = useState<string | null>(null)
  const [formParentName, setFormParentName] = useState<string>('')
  const [formDepth, setFormDepth] = useState(0)
  const [editingId, setEditingId] = useState<string | null>(null)

  // Carica albero tassonomico
  const { data: tree = [], isLoading } = useQuery({
    queryKey: ['labels-tree'],
    queryFn: () => labelsApi.getTree(),
  })

  // Conta i nodi totali
  function countNodes(nodes: LabelTreeResponse[]): number {
    return nodes.reduce((acc, n) => acc + 1 + countNodes(n.children), 0)
  }
  const totalNodes = countNodes(tree)

  // Crea nodo
  const createMutation = useMutation({
    mutationFn: (data: { name: string; color?: string; description?: string; parent_id?: string | null }) =>
      labelsApi.create({ name: data.name, color: data.color || null, description: data.description || null, parent_id: data.parent_id }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['labels-tree'] })
      queryClient.invalidateQueries({ queryKey: ['labels'] })
      toast.success('Nodo creato')
      closeForm()
    },
    onError: (e) => toast.error(getErrorMessage(e)),
  })

  // Aggiorna nodo
  const updateMutation = useMutation({
    mutationFn: ({ id, data }: { id: string; data: { name: string; color?: string; description?: string } }) =>
      labelsApi.update(id, { name: data.name, color: data.color || null, description: data.description || null }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['labels-tree'] })
      queryClient.invalidateQueries({ queryKey: ['labels'] })
      toast.success('Nodo aggiornato')
      closeForm()
    },
    onError: (e) => toast.error(getErrorMessage(e)),
  })

  // Elimina nodo (elimina anche tutti i figli in cascata)
  const deleteMutation = useMutation({
    mutationFn: (id: string) => labelsApi.delete(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['labels-tree'] })
      queryClient.invalidateQueries({ queryKey: ['labels'] })
      toast.success('Nodo eliminato')
    },
    onError: (e) => toast.error(getErrorMessage(e)),
  })

  function openCreate(parentNode: LabelTreeResponse | null = null, depth = 0) {
    setEditingId(null)
    setFormName('')
    setFormColor('')
    setFormDescription('')
    setFormParentId(parentNode?.id ?? null)
    setFormParentName(parentNode?.name ?? '')
    setFormDepth(depth)
    setShowForm(true)
  }

  function openEdit(node: LabelTreeResponse, depth: number) {
    setEditingId(node.id)
    setFormName(node.name)
    setFormColor(node.color ?? '')
    setFormDescription(node.description ?? '')
    setFormParentId(node.parent_id)
    setFormParentName('')
    setFormDepth(depth)
    setShowForm(true)
  }

  function closeForm() {
    setShowForm(false)
    setEditingId(null)
    setFormName('')
    setFormColor('')
    setFormDescription('')
    setFormParentId(null)
    setFormParentName('')
  }

  function handleDelete(node: LabelTreeResponse) {
    const hasChildren = node.children.length > 0
    const msg = hasChildren
      ? `Eliminare "${node.name}" e tutti i suoi ${node.children.length} sottonodi? Verranno rimossi anche dai messaggi.`
      : `Eliminare "${node.name}"? Verra' rimosso anche dai messaggi.`
    if (confirm(msg)) {
      deleteMutation.mutate(node.id)
    }
  }

  function handleSubmit() {
    if (!formName.trim()) return toast.error('Il nome e\' obbligatorio')
    if (formColor && !/^#[0-9A-Fa-f]{6}$/.test(formColor)) {
      return toast.error('Il colore deve essere in formato esadecimale #RRGGBB')
    }
    if (editingId) {
      updateMutation.mutate({
        id: editingId,
        data: { name: formName.trim(), color: formColor, description: formDescription.trim() },
      })
    } else {
      createMutation.mutate({
        name: formName.trim(),
        color: formColor,
        description: formDescription.trim(),
        parent_id: formParentId,
      })
    }
  }

  const levelLabel = LEVEL_LABELS[formDepth] ?? `Livello ${formDepth}`
  const levelColor = LEVEL_COLORS[formDepth] ?? 'bg-gray-100 text-gray-700'

  return (
    <div className="flex flex-col h-full">
      {/* Header */}
      <div className="border-b bg-background px-6 py-4 flex items-center justify-between">
        <div>
          <h1 className="text-xl font-semibold flex items-center gap-2">
            <Tags className="h-5 w-5 text-primary" />
            Tassonomia di Classificazione
          </h1>
          <p className="text-sm text-muted-foreground">
            Organizza la classificazione dei messaggi in una struttura gerarchica a 3 livelli
          </p>
        </div>
        <Button onClick={() => openCreate(null, 0)}>
          <Plus className="h-4 w-4 mr-2" />
          Nuovo Ambito
        </Button>
      </div>

      {/* Legenda livelli */}
      <div className="px-6 py-3 border-b bg-muted/20 flex items-center gap-6 text-sm flex-wrap">
        {LEVEL_LABELS.map((label, i) => (
          <div key={label} className="flex items-center gap-2">
            <span className={cn('px-2 py-0.5 rounded-full border text-xs font-medium', LEVEL_COLORS[i])}>
              {label}
            </span>
            <span className="text-muted-foreground text-xs">
              {i === 0 ? 'Area aziendale principale' : i === 1 ? 'Processo / sotto-area' : 'Classificazione assegnabile ai messaggi'}
            </span>
          </div>
        ))}
        <span className="ml-auto text-xs text-muted-foreground">{totalNodes} nodi totali</span>
      </div>

      {/* Albero */}
      <div className="flex-1 overflow-y-auto p-6">
        {isLoading ? (
          <div className="flex justify-center py-12">
            <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
          </div>
        ) : tree.length === 0 ? (
          <div className="text-center py-16 text-muted-foreground">
            <Tags className="h-14 w-14 mx-auto mb-4 opacity-20" />
            <p className="text-lg font-medium">Nessuna tassonomia configurata</p>
            <p className="text-sm mt-1 max-w-md mx-auto">
              Crea un Ambito per iniziare a strutturare la classificazione dei messaggi PEC.
              Ogni Ambito puo' contenere Processi, che a loro volta contengono Classificazioni.
            </p>
            <Button className="mt-6" onClick={() => openCreate(null, 0)}>
              <Plus className="h-4 w-4 mr-2" />
              Crea il primo Ambito
            </Button>
          </div>
        ) : (
          <div className="space-y-2 max-w-3xl">
            {tree.map((root) => (
              <TreeNode
                key={root.id}
                node={root}
                depth={0}
                onAddChild={(parent, depth) => openCreate(parent, depth)}
                onEdit={openEdit}
                onDelete={handleDelete}
              />
            ))}
          </div>
        )}
      </div>

      {/* Dialog crea/modifica nodo */}
      <Dialog open={showForm} onOpenChange={(o) => !o && closeForm()}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2">
              {editingId ? 'Modifica nodo' : `Nuovo ${levelLabel}`}
              <span className={cn('text-xs px-2 py-0.5 rounded-full border font-normal', levelColor)}>
                {levelLabel}
              </span>
            </DialogTitle>
          </DialogHeader>

          <div className="space-y-4 mt-2">
            {/* Parent path (solo in creazione) */}
            {!editingId && formParentName && (
              <div className="flex items-center gap-2 text-sm text-muted-foreground bg-muted/40 rounded-lg px-3 py-2">
                <Tags className="h-4 w-4 flex-shrink-0" />
                <span>Sotto: <strong>{formParentName}</strong></span>
              </div>
            )}

            <div className="space-y-2">
              <Label>Nome *</Label>
              <Input
                value={formName}
                onChange={(e) => setFormName(e.target.value)}
                placeholder={`Es. ${levelLabel === 'Ambito' ? 'Legale' : levelLabel === 'Processo' ? 'Contratti' : 'NDA'}`}
                autoFocus
              />
            </div>

            <div className="space-y-2">
              <Label>Descrizione (opzionale)</Label>
              <Input
                value={formDescription}
                onChange={(e) => setFormDescription(e.target.value)}
                placeholder="Breve descrizione del nodo..."
              />
            </div>

            <div className="space-y-2">
              <Label>Colore (opzionale)</Label>
              <div className="flex items-center gap-3">
                <Input
                  value={formColor}
                  onChange={(e) => setFormColor(e.target.value)}
                  placeholder="#3B82F6"
                  maxLength={7}
                  className="font-mono"
                />
                {formColor && /^#[0-9A-Fa-f]{6}$/.test(formColor) && (
                  <div
                    className="h-8 w-8 rounded-md border flex-shrink-0"
                    style={{ backgroundColor: formColor }}
                  />
                )}
                {/* Palette colori rapidi */}
                <div className="flex gap-1">
                  {['#3B82F6', '#8B5CF6', '#10B981', '#F59E0B', '#EF4444', '#6B7280'].map((c) => (
                    <button
                      key={c}
                      type="button"
                      onClick={() => setFormColor(c)}
                      className="h-6 w-6 rounded-full border-2 hover:scale-110 transition-transform"
                      style={{ backgroundColor: c, borderColor: formColor === c ? '#1e40af' : 'transparent' }}
                      title={c}
                    />
                  ))}
                </div>
              </div>
            </div>
          </div>

          <DialogFooter className="mt-4">
            <Button variant="outline" onClick={closeForm}>Annulla</Button>
            <Button
              onClick={handleSubmit}
              isLoading={createMutation.isPending || updateMutation.isPending}
            >
              {editingId ? 'Salva modifiche' : `Crea ${levelLabel}`}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  )
}
