import { useState, useEffect, useCallback, useMemo, useRef } from 'react'
import { useNavigate } from 'react-router-dom'
import { Plus, Search, Network, MoreHorizontal, Upload, ChevronDown } from 'lucide-react'
import { cn } from '@/lib/utils'
import { networkDiagramsApi } from '@/api'
import { toast } from '@/lib/toast'
import { CATEGORY_COLORS } from '@/components/network/nodes/deviceRegistry'
import type { NetworkDiagramListItem, DiagramImportData } from '@/types'

const OTHER_COLOR = '#4f5666'

function TopologyBar({ categoryCounts, nodeCount }: { categoryCounts: Record<string, number>; nodeCount: number }) {
  if (nodeCount === 0) return null
  const sorted = Object.entries(categoryCounts).sort(([, a], [, b]) => b - a)
  const tooltipLabel = sorted.map(([cat, count]) => `${count} ${cat}`).join(' · ')
  return (
    <div className="group/bar relative flex h-2 w-full overflow-hidden rounded-full" title={tooltipLabel}>
      {sorted.map(([cat, count]) => (
        <div
          key={cat}
          style={{
            width: `${(count / nodeCount) * 100}%`,
            backgroundColor: CATEGORY_COLORS[cat] ?? OTHER_COLOR,
          }}
        />
      ))}
    </div>
  )
}

export default function NetworkDiagramsPage() {
  const navigate = useNavigate()
  const [diagrams, setDiagrams] = useState<NetworkDiagramListItem[]>([])
  const [loading, setLoading] = useState(true)
  const [search, setSearch] = useState('')
  const [clientFilter, setClientFilter] = useState<string | null>(null)
  const [clientOptions, setClientOptions] = useState<string[]>([])
  const [clientDropdownOpen, setClientDropdownOpen] = useState(false)
  const [clientSearch, setClientSearch] = useState('')
  const [menuOpenId, setMenuOpenId] = useState<string | null>(null)
  const [confirmArchiveId, setConfirmArchiveId] = useState<string | null>(null)
  const clientDropdownRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (!clientDropdownOpen) return
    const handleClick = (e: MouseEvent) => {
      if (clientDropdownRef.current && !clientDropdownRef.current.contains(e.target as Node)) {
        setClientDropdownOpen(false)
      }
    }
    document.addEventListener('mousedown', handleClick)
    return () => document.removeEventListener('mousedown', handleClick)
  }, [clientDropdownOpen])

  const loadDiagrams = useCallback(async () => {
    try {
      const params: Record<string, string> = {}
      if (clientFilter) params.client_name = clientFilter
      if (search) params.search = search
      const data = await networkDiagramsApi.list(params)
      setDiagrams(data)
    } catch {
      toast.error('Failed to load diagrams')
    } finally {
      setLoading(false)
    }
  }, [clientFilter, search])

  const loadClients = useCallback(async () => {
    try {
      const clients = await networkDiagramsApi.listClients()
      setClientOptions(clients)
    } catch { /* ignore */ }
  }, [])

  useEffect(() => { loadDiagrams() }, [loadDiagrams])
  useEffect(() => { loadClients() }, [loadClients])

  const filteredClients = useMemo(() => {
    if (!clientSearch) return clientOptions
    const lower = clientSearch.toLowerCase()
    return clientOptions.filter(c => c.toLowerCase().includes(lower))
  }, [clientOptions, clientSearch])

  const handleDuplicate = useCallback(async (id: string) => {
    try {
      const dup = await networkDiagramsApi.duplicate(id)
      toast.success(`Created: ${dup.name}`)
      loadDiagrams()
    } catch {
      toast.error('Failed to duplicate')
    }
    setMenuOpenId(null)
  }, [loadDiagrams])

  const handleArchive = useCallback(async (id: string) => {
    try {
      await networkDiagramsApi.archive(id)
      toast.success('Diagram archived')
      loadDiagrams()
    } catch {
      toast.error('Failed to archive')
    }
    setMenuOpenId(null)
    setConfirmArchiveId(null)
  }, [loadDiagrams])

  const handleImport = useCallback(async () => {
    const input = document.createElement('input')
    input.type = 'file'
    input.accept = '.json'
    input.onchange = async (e) => {
      const file = (e.target as HTMLInputElement).files?.[0]
      if (!file) return
      try {
        const text = await file.text()
        const data = JSON.parse(text) as DiagramImportData
        const result = await networkDiagramsApi.importJson(data)
        if (result.warnings.length > 0) {
          toast.warning(`Imported with warnings: ${result.warnings.join(', ')}`)
        } else {
          toast.success('Diagram imported')
        }
        navigate(`/network-diagrams/${result.diagram.id}`)
      } catch {
        toast.error('Failed to import — check that the file is a valid diagram JSON')
      }
    }
    input.click()
  }, [navigate])

  const formatDate = (dateStr: string) => {
    return new Date(dateStr).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
  }

  return (
    <div className="mx-auto max-w-6xl px-6 py-8">
      <div className="mb-6 flex items-start justify-between">
        <div>
          <h1 className="font-heading text-2xl font-bold text-heading">Network Maps</h1>
          <p className="mt-1 text-sm text-muted-foreground">Visual network topology documentation for your clients</p>
        </div>
        <div className="flex gap-2">
          <button
            onClick={handleImport}
            className="flex items-center gap-1.5 rounded border border-default px-3 py-2 text-sm text-primary hover:border-hover"
          >
            <Upload size={14} />
            Import
          </button>
          <button
            onClick={() => navigate('/network-diagrams/new')}
            className="flex items-center gap-1.5 rounded bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90"
          >
            <Plus size={14} />
            New Diagram
          </button>
        </div>
      </div>

      <div className="mb-6 flex gap-3">
        <div className="relative flex-1">
          <Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
          <input
            type="text"
            placeholder="Search diagrams..."
            value={search}
            onChange={e => setSearch(e.target.value)}
            className="w-full rounded border border-default bg-input pl-9 pr-3 py-2 text-sm text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none"
          />
        </div>
        <div className="relative w-48" ref={clientDropdownRef}>
          <button
            onClick={() => setClientDropdownOpen(prev => !prev)}
            className="flex w-full items-center justify-between rounded border border-default bg-input px-3 py-2 text-sm text-primary"
          >
            <span className={clientFilter ? 'text-primary' : 'text-muted-foreground'}>
              {clientFilter || 'All clients'}
            </span>
            <ChevronDown size={14} className="shrink-0 text-muted-foreground" />
          </button>
          {clientDropdownOpen && (
            <div className="absolute left-0 top-full z-50 mt-1 w-full rounded border border-default bg-card shadow-lg">
              <div className="p-2">
                <input
                  type="text"
                  placeholder="Search clients..."
                  value={clientSearch}
                  onChange={e => setClientSearch(e.target.value)}
                  className="w-full rounded border border-default bg-input px-2 py-1 text-xs text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none"
                  autoFocus
                />
              </div>
              <div className="max-h-48 overflow-y-auto">
                <button
                  onClick={() => { setClientFilter(null); setClientDropdownOpen(false); setClientSearch('') }}
                  className={cn('w-full px-3 py-1.5 text-left text-xs hover:bg-elevated', !clientFilter && 'text-accent')}
                >
                  All clients
                </button>
                {filteredClients.map(c => (
                  <button
                    key={c}
                    onClick={() => { setClientFilter(c); setClientDropdownOpen(false); setClientSearch('') }}
                    className={cn('w-full px-3 py-1.5 text-left text-xs text-primary hover:bg-elevated', clientFilter === c && 'text-accent')}
                  >
                    {c}
                  </button>
                ))}
              </div>
            </div>
          )}
        </div>
      </div>

      {loading && (
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
          {[1, 2, 3].map(i => (
            <div key={i} className="h-40 animate-pulse rounded-lg border border-default bg-card" />
          ))}
        </div>
      )}

      {!loading && diagrams.length === 0 && (
        <div className="flex flex-col items-center justify-center py-20">
          <Network size={48} className="mb-4 text-muted-foreground" />
          <h2 className="font-heading text-lg font-semibold text-heading">No network maps yet</h2>
          <p className="mt-1 text-sm text-muted-foreground">Create your first network diagram to get started</p>
          <button
            onClick={() => navigate('/network-diagrams/new')}
            className="mt-4 rounded bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90"
          >
            Create First Diagram
          </button>
        </div>
      )}

      {!loading && diagrams.length > 0 && (
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
          {diagrams.map(d => (
            <div
              key={d.id}
              onClick={() => navigate(`/network-diagrams/${d.id}`)}
              className="group relative cursor-pointer rounded-lg border border-default bg-card p-4 hover:border-hover"
            >
              <div className="mb-2 flex items-start justify-between">
                <h3 className="font-heading text-sm font-semibold text-heading">{d.name}</h3>
                <button
                  onClick={e => { e.stopPropagation(); setMenuOpenId(menuOpenId === d.id ? null : d.id) }}
                  className="rounded p-1 text-muted-foreground opacity-0 hover:bg-elevated group-hover:opacity-100"
                >
                  <MoreHorizontal size={14} />
                </button>
              </div>
              {d.client_name && (
                <span className="mb-2 inline-block rounded-full bg-elevated px-2 py-0.5 text-[10px] text-muted-foreground">
                  {d.client_name}
                </span>
              )}
              {d.description && (
                <p className="mb-3 line-clamp-2 text-xs text-muted-foreground">{d.description}</p>
              )}
              {d.node_count > 0 && (
                <div className="mb-2">
                  <TopologyBar categoryCounts={d.category_counts} nodeCount={d.node_count} />
                </div>
              )}
              <div className="flex items-center justify-between text-[10px] text-muted-foreground">
                <span>{d.node_count} device{d.node_count !== 1 ? 's' : ''}</span>
                <span>{formatDate(d.created_at)}</span>
              </div>

              {menuOpenId === d.id && (
                <div className="absolute right-2 top-10 z-50 w-44 rounded border border-default bg-card py-1 shadow-lg">
                  {confirmArchiveId === d.id ? (
                    <>
                      <p className="px-3 py-1.5 text-[10px] text-muted-foreground">Archive this diagram?</p>
                      <div className="flex gap-1 px-2 pb-1.5">
                        <button
                          onClick={e => { e.stopPropagation(); setConfirmArchiveId(null) }}
                          className="flex-1 rounded border border-default px-2 py-1 text-[10px] text-primary hover:bg-elevated"
                        >
                          Cancel
                        </button>
                        <button
                          onClick={e => { e.stopPropagation(); handleArchive(d.id) }}
                          className="flex-1 rounded bg-red-500/20 px-2 py-1 text-[10px] font-medium text-red-400 hover:bg-red-500/30"
                        >
                          Archive
                        </button>
                      </div>
                    </>
                  ) : (
                    <>
                      <button
                        onClick={e => { e.stopPropagation(); navigate(`/network-diagrams/${d.id}`) }}
                        className="w-full px-3 py-1.5 text-left text-xs text-primary hover:bg-elevated"
                      >
                        Open
                      </button>
                      <button
                        onClick={e => { e.stopPropagation(); handleDuplicate(d.id) }}
                        className="w-full px-3 py-1.5 text-left text-xs text-primary hover:bg-elevated"
                      >
                        Duplicate
                      </button>
                      <button
                        onClick={e => { e.stopPropagation(); setConfirmArchiveId(d.id) }}
                        className="w-full px-3 py-1.5 text-left text-xs text-red-400 hover:bg-elevated"
                      >
                        Archive…
                      </button>
                    </>
                  )}
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  )
}
