import { useState, useEffect } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { Save, FlaskConical, AlertCircle } from 'lucide-react'
import { listMaterials, saveCadPartMaterials } from '../../api/materials'
import MaterialInput from '../shared/MaterialInput'
import MaterialWizard from '../MaterialWizard'

interface CadPartRow {
  part_name: string
  material: string
}

interface ExcelComponent {
  part_name: string | null
  material: string | null
  component_type: string | null
  column_index: number
}

interface Props {
  orderId: string
  itemId: string
  partNames: string[]            // from cad_parsed_objects
  savedMaterials: CadPartRow[]   // from cad_part_materials
  excelComponents?: ExcelComponent[]  // from item.components (Excel data)
}

function normName(s: string) {
  return s.trim().toLowerCase()
}

export default function CadPartMaterials({ orderId, itemId, partNames, savedMaterials, excelComponents = [] }: Props) {
  const qc = useQueryClient()
  const [wizardOpen, setWizardOpen] = useState(false)
  const [wizardTargetIdx, setWizardTargetIdx] = useState<number | null>(null)

  const initRows = (): CadPartRow[] =>
    partNames.map((name) => {
      // 1. Use saved value if present
      const saved = savedMaterials.find((s) => s.part_name === name)
      if (saved) return { part_name: name, material: saved.material }
      // 2. Fall back to Excel component data (case-insensitive match)
      const excelMatch = excelComponents.find(
        (c) => c.part_name && normName(c.part_name) === normName(name),
      )
      return { part_name: name, material: excelMatch?.material ?? '' }
    })

  const [rows, setRows] = useState<CadPartRow[]>(initRows)

  // Re-sync when props change (e.g. after save or STEP file change)
  useEffect(() => {
    setRows(initRows())
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [partNames.join(','), savedMaterials.length, excelComponents.length])

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

  const saveMut = useMutation({
    mutationFn: () => saveCadPartMaterials(orderId, itemId, rows.filter((r) => r.material.trim())),
    onSuccess: () => {
      toast.success('Materials saved')
      qc.invalidateQueries({ queryKey: ['order', orderId] })
    },
    onError: (e: any) => toast.error(e.response?.data?.detail || 'Save failed'),
  })

  const isDirty = rows.some((r) => {
    const saved = savedMaterials.find((s) => s.part_name === r.part_name)?.material ?? ''
    return r.material !== saved
  })

  const missingCount = rows.filter((r) => !r.material.trim()).length

  const setMaterial = (idx: number, value: string) =>
    setRows((prev) => prev.map((r, i) => (i === idx ? { ...r, material: value } : r)))

  return (
    <div className="mt-4">
      <div className="flex items-center gap-2 mb-2">
        <FlaskConical size={14} className="text-content-muted" />
        <p className="text-xs font-semibold text-content-muted uppercase tracking-wide">
          CAD Part Materials ({partNames.length})
        </p>
        {missingCount > 0 && (
          <span className="ml-auto flex items-center gap-1 text-xs font-medium text-red-600">
            <AlertCircle size={12} />
            {missingCount} missing
          </span>
        )}
      </div>

      <div className="border border-border-default rounded-lg overflow-hidden">
        {/* Header */}
        <div className="grid grid-cols-2 bg-surface-alt border-b border-border-default px-3 py-1.5">
          <p className="text-xs font-semibold text-content-muted uppercase tracking-wide">Part Name</p>
          <p className="text-xs font-semibold text-content-muted uppercase tracking-wide">Material</p>
        </div>

        {/* Rows */}
        {rows.map((row, idx) => {
          const missing = !row.material.trim()
          return (
            <div
              key={row.part_name}
              className={`grid grid-cols-2 border-b border-border-light last:border-b-0 ${
                missing
                  ? 'bg-red-50'
                  : idx % 2 === 0 ? 'bg-surface' : 'bg-surface-alt/50'
              }`}
            >
              <div className="px-3 py-2 flex items-center gap-2">
                {missing && <AlertCircle size={12} className="text-red-400 shrink-0" />}
                <span
                  className={`text-sm font-mono truncate ${missing ? 'text-red-700' : 'text-content'}`}
                  title={row.part_name}
                >
                  {row.part_name}
                </span>
              </div>
              <div className="px-2 py-1.5">
                <MaterialInput
                  value={row.material}
                  onChange={(v) => setMaterial(idx, v)}
                  library={library}
                  missing={missing}
                  onOpenWizard={() => {
                    setWizardTargetIdx(idx)
                    setWizardOpen(true)
                  }}
                />
              </div>
            </div>
          )
        })}
      </div>

      {(isDirty || missingCount > 0) && (
        <div className="mt-3 flex items-center gap-3">
          {isDirty && (
            <button
              onClick={() => saveMut.mutate()}
              disabled={saveMut.isPending}
              className="btn-primary text-sm"
            >
              <Save size={14} />
              {saveMut.isPending ? 'Saving...' : 'Save Materials'}
            </button>
          )}
          {missingCount > 0 && !isDirty && (
            <p className="text-xs text-red-600 flex items-center gap-1">
              <AlertCircle size={12} />
              {missingCount} part{missingCount !== 1 ? 's' : ''} have no material assigned
            </p>
          )}
        </div>
      )}

      {/* Material Wizard (opened from MaterialInput) */}
      <MaterialWizard
        open={wizardOpen}
        onClose={() => { setWizardOpen(false); setWizardTargetIdx(null) }}
        onCreated={(name) => {
          if (wizardTargetIdx !== null) {
            setMaterial(wizardTargetIdx, name)
          }
          setWizardTargetIdx(null)
        }}
      />
    </div>
  )
}
