import { useState, useEffect, useCallback, useMemo, useRef } from 'react'
import { useNavigate } from 'react-router-dom'
import { Plus, Search, Network, MoreHorizontal, Upload, ChevronDown, FileJson, FileOutput, ExternalLink, Copy, Archive } 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 [importMenuOpen, setImportMenuOpen] = useState(false)
  const clientDropdownRef = useRef<HTMLDivElement>(null)
  const importMenuRef = useRef<HTMLDivElement>(null)
  const drawioListImportRef = useRef<HTMLInputElement>(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])

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

  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 handleListDrawioImport = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    if (!file) return
    e.target.value = ''
    try {
      const { parseDrawioXml } = await import('@/lib/drawio-import')
      const text = await file.text()
      const { nodes: importedNodes, edges: importedEdges, warnings } = parseDrawioXml(text)
      const result = await networkDiagramsApi.importJson({
        schemaVersion: 1,
        name: file.name.replace(/\.drawio$/i, '') || 'Imported Diagram',
        client_name: null,
        description: null,
        nodes: importedNodes,
        edges: importedEdges,
      })
      const allWarnings = [...warnings, ...result.warnings]
      if (allWarnings.length > 0) {
        toast.warning(`Imported with ${allWarnings.length} warning(s)`)
      } else {
        toast.success('Imported successfully')
      }
      navigate(`/network-diagrams/${result.diagram.id}`)
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'Unknown error'
      toast.error(`Import failed: ${msg}`)
    }
  }, [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">
          {/* Single "Import" dropdown replacing two separate buttons */}
          <div className="relative" ref={importMenuRef}>
            <button
              onClick={() => setImportMenuOpen(prev => !prev)}
              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
              <ChevronDown size={12} className="text-muted-foreground" />
            </button>
            {importMenuOpen && (
              <div className="absolute right-0 top-full z-50 mt-1 w-44 rounded border border-default bg-card py-1 shadow-lg">
                <button
                  onClick={() => { setImportMenuOpen(false); handleImport() }}
                  className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated"
                >
                  <FileJson size={13} />
                  <div className="text-left">
                    <div>Import JSON</div>
                    <div className="text-[10px] text-muted-foreground">ResolutionFlow format</div>
                  </div>
                </button>
                <button
                  onClick={() => { setImportMenuOpen(false); drawioListImportRef.current?.click() }}
                  className="flex w-full items-center gap-2 px-3 py-2 text-xs text-primary hover:bg-elevated"
                >
                  <FileOutput size={13} />
                  <div className="text-left">
                    <div>Import draw.io</div>
                    <div className="text-[10px] text-muted-foreground">.drawio or .xml file</div>
                  </div>
                </button>
              </div>
            )}
          </div>
          <input
            ref={drawioListImportRef}
            type="file"
            accept=".drawio,.xml"
            className="hidden"
            onChange={handleListDrawioImport}
          />
          <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="rounded-lg border border-default bg-card overflow-hidden">
          <div className="grid md:grid-cols-[1fr_380px]">
            {/* Left: mini topology preview */}
            <div className="relative flex items-center justify-center bg-[#0e1016] p-8 md:p-12 min-h-[280px]">
              {/* Dot grid background */}
              <svg className="absolute inset-0 h-full w-full opacity-20" xmlns="http://www.w3.org/2000/svg">
                <defs>
                  <pattern id="dots" x="0" y="0" width="24" height="24" patternUnits="userSpaceOnUse">
                    <circle cx="1" cy="1" r="1" fill="#4f5666" />
                  </pattern>
                </defs>
                <rect width="100%" height="100%" fill="url(#dots)" />
              </svg>
              {/* Static topology SVG */}
              <svg viewBox="0 0 460 240" className="relative w-full max-w-md" xmlns="http://www.w3.org/2000/svg">
                {/* Edges */}
                <line x1="230" y1="48" x2="130" y2="130" stroke="#2a2e3a" strokeWidth="1.5" />
                <line x1="230" y1="48" x2="230" y2="130" stroke="#2a2e3a" strokeWidth="1.5" />
                <line x1="230" y1="48" x2="330" y2="130" stroke="#2a2e3a" strokeWidth="1.5" />
                <line x1="130" y1="130" x2="80" y2="210" stroke="#2a2e3a" strokeWidth="1.5" strokeDasharray="4 3" />
                <line x1="130" y1="130" x2="180" y2="210" stroke="#2a2e3a" strokeWidth="1.5" strokeDasharray="4 3" />
                <line x1="330" y1="130" x2="280" y2="210" stroke="#2a2e3a" strokeWidth="1.5" strokeDasharray="4 3" />
                <line x1="330" y1="130" x2="380" y2="210" stroke="#2a2e3a" strokeWidth="1.5" strokeDasharray="4 3" />
                {/* Firewall node */}
                <rect x="196" y="16" width="68" height="40" rx="6" fill="#1e2028" stroke="#3d4252" strokeWidth="1" />
                <rect x="207" y="22" width="14" height="10" rx="2" fill="#f87171" opacity="0.9" />
                <rect x="225" y="22" width="6" height="10" rx="1" fill="#3d4252" />
                <rect x="235" y="22" width="20" height="10" rx="2" fill="#3d4252" />
                <text x="230" y="46" textAnchor="middle" fill="#848b9b" fontSize="9" fontFamily="monospace">Firewall</text>
                {/* Switch node */}
                <rect x="96" y="108" width="68" height="40" rx="6" fill="#1e2028" stroke="#3d4252" strokeWidth="1" />
                <circle cx="112" cy="124" r="4" fill="#34d399" opacity="0.9" />
                <circle cx="122" cy="124" r="4" fill="#34d399" opacity="0.9" />
                <circle cx="132" cy="124" r="4" fill="#fbbf24" opacity="0.8" />
                <circle cx="142" cy="124" r="4" fill="#34d399" opacity="0.9" />
                <text x="130" y="140" textAnchor="middle" fill="#848b9b" fontSize="9" fontFamily="monospace">Core Switch</text>
                {/* Router node */}
                <rect x="196" y="108" width="68" height="40" rx="6" fill="#1e2028" stroke="#60a5fa" strokeWidth="1" />
                <circle cx="230" cy="124" r="10" fill="none" stroke="#60a5fa" strokeWidth="1.5" opacity="0.7" />
                <circle cx="230" cy="124" r="5" fill="none" stroke="#60a5fa" strokeWidth="1" opacity="0.5" />
                <line x1="220" y1="124" x2="240" y2="124" stroke="#60a5fa" strokeWidth="1" opacity="0.6" />
                <text x="230" y="140" textAnchor="middle" fill="#93c5fd" fontSize="9" fontFamily="monospace">Router</text>
                {/* Server farm */}
                <rect x="296" y="108" width="68" height="40" rx="6" fill="#1e2028" stroke="#3d4252" strokeWidth="1" />
                <rect x="308" y="116" width="44" height="7" rx="2" fill="#2a2e3a" />
                <rect x="308" y="127" width="44" height="7" rx="2" fill="#2a2e3a" />
                <circle cx="345" cy="119.5" r="2" fill="#34d399" opacity="0.9" />
                <circle cx="345" cy="130.5" r="2" fill="#34d399" opacity="0.9" />
                <text x="330" y="140" textAnchor="middle" fill="#848b9b" fontSize="9" fontFamily="monospace">Servers</text>
                {/* Leaf nodes */}
                <rect x="46" y="190" width="52" height="34" rx="5" fill="#1e2028" stroke="#2a2e3a" strokeWidth="1" />
                <text x="72" y="211" textAnchor="middle" fill="#4f5666" fontSize="8" fontFamily="monospace">PC × 12</text>
                <rect x="154" y="190" width="52" height="34" rx="5" fill="#1e2028" stroke="#2a2e3a" strokeWidth="1" />
                <text x="180" y="211" textAnchor="middle" fill="#4f5666" fontSize="8" fontFamily="monospace">AP × 4</text>
                <rect x="254" y="190" width="52" height="34" rx="5" fill="#1e2028" stroke="#2a2e3a" strokeWidth="1" />
                <text x="280" y="211" textAnchor="middle" fill="#4f5666" fontSize="8" fontFamily="monospace">NAS</text>
                <rect x="354" y="190" width="52" height="34" rx="5" fill="#1e2028" stroke="#2a2e3a" strokeWidth="1" />
                <text x="380" y="211" textAnchor="middle" fill="#4f5666" fontSize="8" fontFamily="monospace">VM × 6</text>
              </svg>
            </div>

            {/* Right: value prop + CTA */}
            <div className="flex flex-col justify-center border-l border-default p-8">
              <div className="mb-1 flex items-center gap-2">
                <Network size={14} className="text-accent" />
                <span className="text-[11px] font-semibold uppercase tracking-wider text-accent">Network Maps</span>
              </div>
              <h2 className="font-heading text-xl font-bold text-heading leading-snug">
                Document every client's infrastructure — once
              </h2>
              <p className="mt-3 text-sm leading-relaxed text-muted-foreground">
                Drag-and-drop topology diagrams that live next to your tickets. Generate a first draft from a plain-text description, then keep it up to date as networks change.
              </p>
              <ul className="mt-4 space-y-2 text-xs text-muted-foreground">
                <li className="flex items-center gap-2">
                  <div className="h-1.5 w-1.5 rounded-full bg-accent" />
                  AI topology generation from natural language
                </li>
                <li className="flex items-center gap-2">
                  <div className="h-1.5 w-1.5 rounded-full bg-accent" />
                  Export to PNG, SVG, PDF, or draw.io
                </li>
                <li className="flex items-center gap-2">
                  <div className="h-1.5 w-1.5 rounded-full bg-accent" />
                  Shared across your whole team instantly
                </li>
              </ul>
              <div className="mt-6 flex flex-col gap-2 sm:flex-row sm:items-center">
                <button
                  onClick={() => navigate('/network-diagrams/new')}
                  className="flex items-center justify-center gap-1.5 rounded bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent/90"
                >
                  <Plus size={14} />
                  Create Network Map
                </button>
                <button
                  onClick={() => { setImportMenuOpen(true) }}
                  className="flex items-center justify-center gap-1.5 rounded border border-default px-4 py-2 text-sm text-primary hover:border-hover"
                >
                  <Upload size={14} />
                  Import existing
                </button>
              </div>
            </div>
          </div>
        </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>
              )}
              {/* Thumbnail preview */}
              {d.thumbnail_url ? (
                <div className="mb-2 overflow-hidden rounded border border-default">
                  <img
                    src={d.thumbnail_url}
                    alt={d.name}
                    className="h-[120px] w-full object-cover"
                    onError={e => { (e.target as HTMLImageElement).style.display = 'none' }}
                  />
                </div>
              ) : (
                <div className="relative mb-2 flex h-[120px] items-center justify-center overflow-hidden rounded border border-default bg-[#0e1016]">
                  <svg className="absolute inset-0 h-full w-full opacity-30" xmlns="http://www.w3.org/2000/svg">
                    <defs>
                      <pattern id={`dots-${d.id}`} x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
                        <circle cx="1" cy="1" r="0.8" fill="#4f5666" />
                      </pattern>
                    </defs>
                    <rect width="100%" height="100%" fill={`url(#dots-${d.id})`} />
                  </svg>
                  <Network size={24} className="relative text-muted-foreground/20" />
                </div>
              )}
              {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="flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-primary hover:bg-elevated"
                      >
                        <ExternalLink size={12} className="text-muted-foreground" />
                        Open
                      </button>
                      <button
                        onClick={e => { e.stopPropagation(); handleDuplicate(d.id) }}
                        className="flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-primary hover:bg-elevated"
                      >
                        <Copy size={12} className="text-muted-foreground" />
                        Duplicate
                      </button>
                      <div className="my-1 border-t border-default" />
                      <button
                        onClick={e => { e.stopPropagation(); setConfirmArchiveId(d.id) }}
                        className="flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-red-400 hover:bg-elevated"
                      >
                        <Archive size={12} />
                        Archive…
                      </button>
                    </>
                  )}
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  )
}
