import { useState, useMemo } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import {
  Plus, Trash2, Pencil, Check, X, FlaskConical, Search, Wand2, Download,
  Wrench, Paintbrush, Shapes, HelpCircle, ChevronDown, ChevronRight, Tag,
} from 'lucide-react'
import {
  listMaterials, createMaterial, updateMaterial, deleteMaterial,
  seedSchaefflerMaterials, addAlias, deleteAlias, seedAliases,
} from '../api/materials'
import type { Material } from '../api/materials'
import MaterialWizard from '../components/MaterialWizard'

const TYPE_GROUPS = [
  { code: '01', label: 'Metals', icon: Wrench, bg: 'bg-slate-50', border: 'border-slate-200', text: 'text-slate-700' },
  { code: '02', label: 'Coatings', icon: Paintbrush, bg: 'bg-status-info-bg', border: 'border-border-default', text: 'text-status-info-text' },
  { code: '03', label: 'Non-metals', icon: Shapes, bg: 'bg-status-warning-bg', border: 'border-border-default', text: 'text-status-warning-text' },
  { code: '04', label: 'Compounds', icon: FlaskConical, bg: 'bg-purple-50', border: 'border-purple-200', text: 'text-purple-700' },
  { code: '05', label: 'Misc', icon: HelpCircle, bg: 'bg-surface-alt', border: 'border-border-default', text: 'text-content-secondary' },
] as const

function getTypeCode(mat: Material): string | null {
  if (mat.schaeffler_code == null) return null
  return String(mat.schaeffler_code).padStart(6, '0').slice(0, 2)
}

interface MaterialGroup {
  code: string | null
  label: string
  icon: typeof Wrench
  bg: string
  border: string
  text: string
  items: Material[]
}

export default function MaterialsPage() {
  const qc = useQueryClient()
  const [search, setSearch] = useState('')
  const [showAdd, setShowAdd] = useState(false)
  const [showWizard, setShowWizard] = useState(false)
  const [newName, setNewName] = useState('')
  const [newDesc, setNewDesc] = useState('')
  const [editingId, setEditingId] = useState<string | null>(null)
  const [editName, setEditName] = useState('')
  const [editDesc, setEditDesc] = useState('')
  const [collapsed, setCollapsed] = useState<Set<string | null>>(new Set())
  const [expandedAliases, setExpandedAliases] = useState<Set<string>>(new Set())
  const [aliasInput, setAliasInput] = useState<Record<string, string>>({})

  const { data: materials = [], isLoading } = useQuery({
    queryKey: ['materials'],
    queryFn: listMaterials,
  })

  const createMut = useMutation({
    mutationFn: () => createMaterial({ name: newName.trim(), description: newDesc.trim() || undefined }),
    onSuccess: () => {
      toast.success('Material added')
      qc.invalidateQueries({ queryKey: ['materials'] })
      setShowAdd(false)
      setNewName('')
      setNewDesc('')
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to add material'),
  })

  const updateMut = useMutation({
    mutationFn: (id: string) => updateMaterial(id, { name: editName.trim(), description: editDesc.trim() || undefined }),
    onSuccess: () => {
      toast.success('Material updated')
      qc.invalidateQueries({ queryKey: ['materials'] })
      setEditingId(null)
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to update'),
  })

  const deleteMut = useMutation({
    mutationFn: deleteMaterial,
    onSuccess: () => {
      toast.success('Material deleted')
      qc.invalidateQueries({ queryKey: ['materials'] })
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to delete'),
  })

  const seedMut = useMutation({
    mutationFn: seedSchaefflerMaterials,
    onSuccess: (data) => {
      if (data.inserted > 0) {
        toast.success(`Imported ${data.inserted} of ${data.total} Schaeffler standard materials`)
      } else {
        toast.info('All Schaeffler standard materials already exist')
      }
      qc.invalidateQueries({ queryKey: ['materials'] })
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to import'),
  })

  const seedAliasMut = useMutation({
    mutationFn: seedAliases,
    onSuccess: (data) => {
      if (data.inserted > 0) {
        toast.success(`Seeded ${data.inserted} aliases (${data.total} total checked)`)
      } else {
        toast.info('All aliases already exist')
      }
      qc.invalidateQueries({ queryKey: ['materials'] })
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to seed aliases'),
  })

  const addAliasMut = useMutation({
    mutationFn: ({ materialId, alias }: { materialId: string; alias: string }) => addAlias(materialId, alias),
    onSuccess: (_data, vars) => {
      toast.success('Alias added')
      qc.invalidateQueries({ queryKey: ['materials'] })
      setAliasInput((prev) => ({ ...prev, [vars.materialId]: '' }))
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to add alias'),
  })

  const deleteAliasMut = useMutation({
    mutationFn: deleteAlias,
    onSuccess: () => {
      toast.success('Alias removed')
      qc.invalidateQueries({ queryKey: ['materials'] })
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Failed to remove alias'),
  })

  const startEdit = (mat: Material) => {
    setEditingId(mat.id)
    setEditName(mat.name)
    setEditDesc(mat.description ?? '')
  }

  const toggleAliases = (id: string) => {
    setExpandedAliases((prev) => {
      const next = new Set(prev)
      if (next.has(id)) next.delete(id)
      else next.add(id)
      return next
    })
  }

  const handleAddAlias = (materialId: string) => {
    const val = (aliasInput[materialId] || '').trim()
    if (val) addAliasMut.mutate({ materialId, alias: val })
  }

  // Search filters include aliases
  const filtered = search.trim()
    ? materials.filter((m) => {
        const q = search.toLowerCase()
        return (
          m.name.toLowerCase().includes(q) ||
          m.description?.toLowerCase().includes(q) ||
          m.aliases.some((a) => a.toLowerCase().includes(q))
        )
      })
    : materials

  // Group filtered materials by type code
  const groups = useMemo((): MaterialGroup[] => {
    const buckets = new Map<string | null, Material[]>()
    for (const m of filtered) {
      const tc = getTypeCode(m)
      if (!buckets.has(tc)) buckets.set(tc, [])
      buckets.get(tc)!.push(m)
    }

    const result: MaterialGroup[] = []
    // Known type groups first
    for (const tg of TYPE_GROUPS) {
      const items = buckets.get(tg.code)
      if (items && items.length > 0) {
        result.push({ code: tg.code, label: tg.label, icon: tg.icon, bg: tg.bg, border: tg.border, text: tg.text, items })
        buckets.delete(tg.code)
      }
    }
    // Custom / non-schaeffler materials
    const custom = buckets.get(null)
    if (custom && custom.length > 0) {
      result.push({ code: null, label: 'Custom', icon: Plus, bg: 'bg-surface-alt', border: 'border-border-default', text: 'text-content-secondary', items: custom })
    }
    return result
  }, [filtered])

  const toggleGroup = (code: string | null) => {
    setCollapsed((prev) => {
      const next = new Set(prev)
      if (next.has(code)) next.delete(code)
      else next.add(code)
      return next
    })
  }

  const totalAliases = materials.reduce((sum, m) => sum + m.aliases.length, 0)

  return (
    <div className="p-8">
      {/* Header */}
      <div className="flex items-center gap-3 mb-6">
        <FlaskConical size={22} className="text-accent" />
        <div className="flex-1">
          <h1 className="text-2xl font-bold text-content">Material Library</h1>
          <p className="text-sm text-content-secondary mt-0.5">
            Shared materials used when assigning CAD part materials to order items.
            {totalAliases > 0 && <span className="ml-2 text-content-muted">({totalAliases} aliases configured)</span>}
          </p>
        </div>
        <button
          onClick={() => {
            if (confirm('Import 35 Schaeffler standard materials? Existing entries will be skipped.'))
              seedMut.mutate()
          }}
          disabled={seedMut.isPending}
          className="btn-secondary text-sm flex items-center gap-1.5"
          title="Import the 35 standard Schaeffler SCHAEFFLER_... materials used in Blender material libraries. Existing entries are skipped."
        >
          <Download size={14} /> {seedMut.isPending ? 'Importing...' : 'Import Standards'}
        </button>
        <button
          onClick={() => {
            if (confirm('Seed material aliases from naming scheme mappings? Existing aliases will be skipped.'))
              seedAliasMut.mutate()
          }}
          disabled={seedAliasMut.isPending}
          className="btn-secondary text-sm flex items-center gap-1.5"
          title="Seed ~100 material aliases from the Schaeffler naming scheme (German descriptions, intermediate codes → SCHAEFFLER_... library names). Existing aliases are skipped."
        >
          <Tag size={14} /> {seedAliasMut.isPending ? 'Seeding...' : 'Seed Aliases'}
        </button>
        <button
          onClick={() => setShowWizard(true)}
          className="btn-secondary text-sm flex items-center gap-1.5"
          title="Open the Schaeffler Wizard — guided tool to set up SCHAEFFLER_... materials and aliases from the standard naming scheme"
        >
          <Wand2 size={14} /> Schaeffler Wizard
        </button>
        <button onClick={() => setShowAdd(!showAdd)} className="btn-primary">
          <Plus size={16} /> Add Material
        </button>
      </div>

      {/* Add form */}
      {showAdd && (
        <div className="card p-4 mb-6 bg-surface-alt flex gap-3 items-end flex-wrap">
          <div className="flex-1 min-w-[160px]">
            <label className="block text-xs font-medium text-content-secondary mb-1">Name *</label>
            <input
              autoFocus
              placeholder="e.g. Steel 100Cr6"
              value={newName}
              onChange={(e) => setNewName(e.target.value)}
              onKeyDown={(e) => e.key === 'Enter' && newName.trim() && createMut.mutate()}
              className="w-full px-3 py-1.5 border border-border-default rounded-md text-sm focus:outline-none focus:border-accent"
            />
          </div>
          <div className="flex-1 min-w-[200px]">
            <label className="block text-xs font-medium text-content-secondary mb-1">Description</label>
            <input
              placeholder="e.g. Bearing steel, hardened"
              value={newDesc}
              onChange={(e) => setNewDesc(e.target.value)}
              onKeyDown={(e) => e.key === 'Enter' && newName.trim() && createMut.mutate()}
              className="w-full px-3 py-1.5 border border-border-default rounded-md text-sm focus:outline-none focus:border-accent"
            />
          </div>
          <div className="flex gap-2">
            <button
              onClick={() => createMut.mutate()}
              disabled={!newName.trim() || createMut.isPending}
              className="btn-primary text-sm"
            >
              {createMut.isPending ? 'Adding...' : 'Add'}
            </button>
            <button onClick={() => setShowAdd(false)} className="btn-secondary text-sm">Cancel</button>
          </div>
        </div>
      )}

      {/* Search */}
      <div className="relative mb-4">
        <Search size={15} className="absolute left-3 top-1/2 -translate-y-1/2 text-content-muted" />
        <input
          type="text"
          placeholder="Search materials or aliases..."
          value={search}
          onChange={(e) => setSearch(e.target.value)}
          className="w-full pl-9 pr-4 py-2 border border-border-default rounded-lg text-sm focus:outline-none focus:border-accent bg-surface"
        />
      </div>

      {/* Grouped table */}
      {isLoading ? (
        <div className="card p-8 text-center text-content-muted text-sm">Loading...</div>
      ) : filtered.length === 0 ? (
        <div className="card p-8 text-center text-content-muted text-sm">
          {search ? 'No materials match your search.' : 'No materials yet. Add the first one above.'}
        </div>
      ) : (
        <div className="space-y-3">
          {groups.map((group) => {
            const Icon = group.icon
            const isCollapsed = collapsed.has(group.code)
            return (
              <div key={group.code ?? 'custom'} className={`card overflow-hidden border ${group.border}`}>
                {/* Group header */}
                <button
                  onClick={() => toggleGroup(group.code)}
                  className={`w-full flex items-center gap-3 px-5 py-3 ${group.bg} hover:brightness-95 transition-all`}
                >
                  {isCollapsed ? <ChevronRight size={16} className={group.text} /> : <ChevronDown size={16} className={group.text} />}
                  <Icon size={16} className={group.text} />
                  <span className={`text-sm font-semibold ${group.text}`}>
                    {group.code ? `${group.code} — ` : ''}{group.label}
                  </span>
                  <span className="text-xs text-content-muted ml-auto">{group.items.length} material{group.items.length !== 1 ? 's' : ''}</span>
                </button>

                {!isCollapsed && (
                  <>
                    {/* Column header */}
                    <div className="grid grid-cols-[2fr_2fr_1fr_1fr_1fr] bg-surface border-b border-border-light px-6 py-1.5">
                      <p className="text-[10px] font-semibold text-content-muted uppercase tracking-wide">Name</p>
                      <p className="text-[10px] font-semibold text-content-muted uppercase tracking-wide">Description</p>
                      <p className="text-[10px] font-semibold text-content-muted uppercase tracking-wide">Source</p>
                      <p className="text-[10px] font-semibold text-content-muted uppercase tracking-wide">Aliases</p>
                      <p className="text-[10px] font-semibold text-content-muted uppercase tracking-wide">Actions</p>
                    </div>

                    {/* Rows */}
                    <div className="divide-y divide-border-light">
                      {group.items.map((mat) => {
                        const aliasesExpanded = expandedAliases.has(mat.id)
                        return (
                          <div key={mat.id}>
                            <div className="grid grid-cols-[2fr_2fr_1fr_1fr_1fr] items-center px-6 py-2.5 gap-3 hover:bg-surface-hover">
                              {editingId === mat.id ? (
                                <div className="col-span-5 flex items-center gap-3 flex-wrap">
                                  <input
                                    autoFocus
                                    value={editName}
                                    onChange={(e) => setEditName(e.target.value)}
                                    placeholder="Name"
                                    className="flex-1 min-w-[140px] px-2 py-1 border border-border-default rounded text-sm focus:outline-none focus:border-accent"
                                  />
                                  <input
                                    value={editDesc}
                                    onChange={(e) => setEditDesc(e.target.value)}
                                    placeholder="Description"
                                    className="flex-1 min-w-[200px] px-2 py-1 border border-border-default rounded text-sm focus:outline-none focus:border-accent"
                                  />
                                  <button
                                    onClick={() => updateMut.mutate(mat.id)}
                                    disabled={!editName.trim() || updateMut.isPending}
                                    className="text-status-success-text hover:text-status-success-text"
                                    title="Save"
                                  >
                                    <Check size={16} />
                                  </button>
                                  <button onClick={() => setEditingId(null)} className="text-content-muted hover:text-content" title="Cancel">
                                    <X size={16} />
                                  </button>
                                </div>
                              ) : (
                                <>
                                  <div className="min-w-0">
                                    <p className="text-sm font-medium text-content truncate">{mat.name}</p>
                                    {mat.schaeffler_code != null && (
                                      <p className="text-xs text-content-muted font-mono">Nr: {mat.schaeffler_code}</p>
                                    )}
                                  </div>
                                  <div className="min-w-0">
                                    <p className="text-sm text-content-muted truncate">{mat.description || '—'}</p>
                                  </div>
                                  <div>
                                    <SourceBadge source={mat.source} />
                                  </div>
                                  <div>
                                    <button
                                      onClick={() => toggleAliases(mat.id)}
                                      className="inline-flex items-center gap-1 text-xs text-content-muted hover:text-content-secondary"
                                      title={`${mat.aliases.length} alias${mat.aliases.length !== 1 ? 'es' : ''} — click to ${aliasesExpanded ? 'collapse' : 'expand'}`}
                                    >
                                      <Tag size={12} />
                                      <span>{mat.aliases.length}</span>
                                      {mat.aliases.length > 0 && (
                                        aliasesExpanded
                                          ? <ChevronDown size={12} />
                                          : <ChevronRight size={12} />
                                      )}
                                    </button>
                                  </div>
                                  <div className="flex items-center gap-1">
                                    <button onClick={() => startEdit(mat)} className="text-content-muted hover:text-content" title="Edit">
                                      <Pencil size={14} />
                                    </button>
                                    <button
                                      onClick={() => {
                                        if (confirm(`Delete material "${mat.name}"?`)) deleteMut.mutate(mat.id)
                                      }}
                                      className="text-content-muted hover:text-red-500"
                                      title="Delete"
                                    >
                                      <Trash2 size={14} />
                                    </button>
                                  </div>
                                </>
                              )}
                            </div>

                            {/* Expandable alias section */}
                            {aliasesExpanded && editingId !== mat.id && (
                              <div className="px-8 pb-3 pt-1 bg-surface-alt/50 border-t border-border-light">
                                <div className="flex flex-wrap gap-1.5 mb-2">
                                  {mat.aliases.length === 0 && (
                                    <span className="text-xs text-content-muted italic">No aliases configured</span>
                                  )}
                                  {mat.aliases.map((alias) => (
                                    <AliasPill
                                      key={alias}
                                      alias={alias}
                                      materialId={mat.id}
                                      onDelete={deleteAliasMut}
                                      materials={materials}
                                    />
                                  ))}
                                </div>
                                <div className="flex items-center gap-2">
                                  <input
                                    type="text"
                                    placeholder="Add alias (e.g. Stahl, brüniert)"
                                    value={aliasInput[mat.id] || ''}
                                    onChange={(e) => setAliasInput((prev) => ({ ...prev, [mat.id]: e.target.value }))}
                                    onKeyDown={(e) => {
                                      if (e.key === 'Enter') handleAddAlias(mat.id)
                                    }}
                                    className="flex-1 max-w-xs px-2 py-1 border border-border-default rounded text-xs focus:outline-none focus:border-accent"
                                  />
                                  <button
                                    onClick={() => handleAddAlias(mat.id)}
                                    disabled={!(aliasInput[mat.id] || '').trim() || addAliasMut.isPending}
                                    className="text-xs text-accent hover:text-accent-hover font-medium disabled:opacity-40"
                                  >
                                    + Add
                                  </button>
                                </div>
                              </div>
                            )}
                          </div>
                        )
                      })}
                    </div>
                  </>
                )}
              </div>
            )
          })}

          {/* Footer count */}
          <div className="text-center py-2">
            <p className="text-xs text-content-muted">
              {filtered.length} of {materials.length} material{materials.length !== 1 ? 's' : ''}
              {totalAliases > 0 && ` · ${totalAliases} aliases`}
            </p>
          </div>
        </div>
      )}

      {/* Wizard modal */}
      <MaterialWizard open={showWizard} onClose={() => setShowWizard(false)} />
    </div>
  )
}

function AliasPill({
  alias,
  materialId,
  onDelete,
  materials,
}: {
  alias: string
  materialId: string
  onDelete: { mutate: (id: string) => void; isPending: boolean }
  materials: Material[]
}) {
  // We need the alias ID for deletion - find it from the material's aliases list
  // Since we only have alias strings from MaterialOut, we need to query the ID
  // We'll use a lazy approach: delete by fetching aliases for this material
  const handleDelete = async () => {
    try {
      const { listAliases: fetchAliases } = await import('../api/materials')
      const aliases = await fetchAliases(materialId)
      const found = aliases.find((a) => a.alias === alias)
      if (found) {
        onDelete.mutate(found.id)
      }
    } catch {
      // Fallback: ignore
    }
  }

  return (
    <span className="inline-flex items-center gap-1 text-xs bg-indigo-50 text-indigo-700 px-2 py-0.5 rounded-full">
      {alias}
      <button
        onClick={handleDelete}
        className="text-indigo-400 hover:text-red-500 ml-0.5"
        title={`Remove alias "${alias}"`}
      >
        <X size={10} />
      </button>
    </span>
  )
}

function SourceBadge({ source }: { source: string }) {
  if (source === 'schaeffler_standard') {
    return (
      <span className="inline-flex items-center gap-1 text-xs font-medium bg-status-success-bg text-status-success-text px-2 py-0.5 rounded-full">
        Standard
      </span>
    )
  }
  if (source === 'cad_import') {
    return (
      <span className="inline-flex items-center gap-1 text-xs font-medium bg-purple-100 text-purple-700 px-2 py-0.5 rounded-full">
        CAD import
      </span>
    )
  }
  return (
    <span className="inline-flex items-center gap-1 text-xs font-medium bg-surface-muted text-content-secondary px-2 py-0.5 rounded-full">
      Manual
    </span>
  )
}
