import { useState, useMemo } from 'react'
import { useNavigate, Link } from 'react-router-dom'
import { useQuery, keepPreviousData } from '@tanstack/react-query'
import {
  ArrowLeft, ArrowRight, Search, Box, Check, ShoppingCart, Trash2,
  ChevronDown, ChevronRight,
} from 'lucide-react'
import { toast } from 'sonner'
import { listProducts } from '../api/products'
import { listOutputTypes } from '../api/outputTypes'
import { createOrder } from '../api/orders'
import { estimatePrice } from '../api/pricing'
import { listGlobalRenderPositions } from '../api/renderPositions'
import { listMaterials } from '../api/materials'
import type { Material } from '../api/materials'
import type { Product, RenderPosition } from '../api/products'
import type { GlobalRenderPosition } from '../api/renderPositions'
import type { OutputType } from '../api/outputTypes'

const formatCurrency = (amount: number) =>
  new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(amount)

const CATEGORIES = [
  { key: 'TRB', label: 'TRB' },
  { key: 'Kugellager', label: 'Kugellager' },
  { key: 'CRB', label: 'CRB' },
  { key: 'Gleitlager', label: 'Gleitlager' },
  { key: 'SRB_TORB', label: 'SRB/TORB' },
  { key: 'Linear_schiene', label: 'Linear' },
  { key: 'Anschlagplatten', label: 'Anschlag' },
]

type WizardStep = 1 | 2 | 3

// Maps product_id → Set of output_type_id
type OutputSelections = Record<string, Set<string>>
// Maps product_id → Set of position_id
type PositionSelections = Record<string, Set<string>>
// Maps product_id → Set of global_render_position_id
type GlobalPositionSelections = Record<string, Set<string>>

export default function NewProductOrderPage() {
  const navigate = useNavigate()
  const [step, setStep] = useState<WizardStep>(1)
  const [searchQ, setSearchQ] = useState('')
  const [categoryFilter, setCategoryFilter] = useState('')
  const [selectedProducts, setSelectedProducts] = useState<Map<string, Product>>(new Map())
  const [outputSelections, setOutputSelections] = useState<OutputSelections>({})
  const [positionSelections, setPositionSelections] = useState<PositionSelections>({})
  const [globalPositionSelections, setGlobalPositionSelections] = useState<GlobalPositionSelections>({})
  const [notes, setNotes] = useState('')
  const [materialOverride, setMaterialOverride] = useState<string>('')
  const [lineOverrides, setLineOverrides] = useState<Record<string, string>>({})
  const [submitting, setSubmitting] = useState(false)

  // ---- Step 1: load products with STEP files ----
  const { data: products, isLoading: productsLoading } = useQuery({
    queryKey: ['wizard-products', searchQ, categoryFilter],
    queryFn: () => listProducts({
      q: searchQ,
      category_key: categoryFilter,
      ready_only: true,
      limit: 200,
    }),
  })

  // ---- Step 2: load all output types (we'll filter client-side per product category) ----
  const { data: allOutputTypes } = useQuery({
    queryKey: ['wizard-output-types'],
    queryFn: () => listOutputTypes(false),
    enabled: step >= 2,
  })

  const { data: allGlobalPositions = [] } = useQuery({
    queryKey: ['global-render-positions'],
    queryFn: listGlobalRenderPositions,
  })

  const { data: allMaterials } = useQuery({
    queryKey: ['materials'],
    queryFn: listMaterials,
    enabled: step >= 3,
  })
  const libMaterials = (allMaterials ?? []).filter((m: Material) => m.hartomat_code !== null).sort((a: Material, b: Material) => a.name.localeCompare(b.name))

  function initPositionsForProduct(product: Product, globals: GlobalRenderPosition[] = []) {
    // Pre-select all per-product positions (if any)
    if ((product.render_positions?.length ?? 0) > 0) {
      setPositionSelections((ps) => ({
        ...ps,
        [product.id]: new Set(product.render_positions!.map((p) => p.id)),
      }))
    }
    // Always pre-select all global positions for every product
    if (globals.length > 0) {
      setGlobalPositionSelections((gs) => ({
        ...gs,
        [product.id]: new Set(globals.map((g) => g.id)),
      }))
    }
  }

  function toggleProduct(product: Product) {
    const willSelect = !selectedProducts.has(product.id)
    setSelectedProducts((prev) => {
      const next = new Map(prev)
      if (next.has(product.id)) {
        next.delete(product.id)
      } else {
        next.set(product.id, product)
      }
      return next
    })
    if (willSelect) {
      initPositionsForProduct(product, allGlobalPositions)
    }
  }

  const allFilteredSelected =
    (products?.length ?? 0) > 0 && (products ?? []).every((p) => selectedProducts.has(p.id))

  function selectAllFiltered() {
    const toInit = (products ?? []).filter((p) => !selectedProducts.has(p.id))
    setSelectedProducts((prev) => {
      const next = new Map(prev)
      ;(products ?? []).forEach((p) => next.set(p.id, p))
      return next
    })
    toInit.forEach((p) => initPositionsForProduct(p, allGlobalPositions))
  }

  function deselectAllFiltered() {
    setSelectedProducts((prev) => {
      const next = new Map(prev)
      ;(products ?? []).forEach((p) => next.delete(p.id))
      return next
    })
  }

  function getCompatibleOutputTypes(categoryKey: string | null): OutputType[] {
    if (!allOutputTypes) return []
    return allOutputTypes.filter((ot) =>
      ot.compatible_categories.length === 0 ||
      (categoryKey && ot.compatible_categories.includes(categoryKey))
    )
  }

  function toggleOutputType(productId: string, outputTypeId: string) {
    setOutputSelections((prev) => {
      const set = new Set(prev[productId] || [])
      if (set.has(outputTypeId)) {
        set.delete(outputTypeId)
      } else {
        set.add(outputTypeId)
      }
      return { ...prev, [productId]: set }
    })
  }

  // Union of all output types compatible with at least one selected product
  const globalOutputTypes = useMemo(() => {
    if (!allOutputTypes || selectedProducts.size === 0) return []
    const seenIds = new Set<string>()
    const result: OutputType[] = []
    for (const product of selectedProducts.values()) {
      for (const ot of getCompatibleOutputTypes(product.category_key)) {
        if (!seenIds.has(ot.id)) {
          seenIds.add(ot.id)
          result.push(ot)
        }
      }
    }
    return result
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedProducts, allOutputTypes])

  function toggleOutputTypeGlobal(otId: string) {
    let compatibleCount = 0
    let selectedCount = 0
    for (const [productId, product] of selectedProducts) {
      const compatible = getCompatibleOutputTypes(product.category_key)
      if (!compatible.some((ot) => ot.id === otId)) continue
      compatibleCount++
      if (outputSelections[productId]?.has(otId)) selectedCount++
    }
    if (compatibleCount === 0) return
    const shouldSelect = selectedCount < compatibleCount
    setOutputSelections((prev) => {
      const next = { ...prev }
      for (const [productId, product] of selectedProducts) {
        const compatible = getCompatibleOutputTypes(product.category_key)
        if (!compatible.some((ot) => ot.id === otId)) continue
        const set = new Set(prev[productId] || [])
        if (shouldSelect) set.add(otId)
        else set.delete(otId)
        next[productId] = set
      }
      return next
    })
  }

  function togglePosition(productId: string, positionId: string) {
    setPositionSelections((prev) => {
      const set = new Set(prev[productId] || [])
      if (set.has(positionId)) set.delete(positionId)
      else set.add(positionId)
      return { ...prev, [productId]: set }
    })
  }

  // Union of all unique per-product position names across selected products that have per-product positions
  const globalPositionNames = useMemo(() => {
    const seen = new Set<string>()
    const result: string[] = []
    for (const product of selectedProducts.values()) {
      for (const pos of product.render_positions ?? []) {
        if (!seen.has(pos.name)) {
          seen.add(pos.name)
          result.push(pos.name)
        }
      }
    }
    return result
  }, [selectedProducts])

  // Global positions apply to all selected products
  const anyProductUsesGlobalPositions = selectedProducts.size > 0

  function toggleGlobalPositionForAll(gpId: string) {
    // Count how many selected products have this global position selected
    const eligibleCount = selectedProducts.size
    let selectedCount = 0
    for (const [productId] of selectedProducts) {
      if (globalPositionSelections[productId]?.has(gpId)) selectedCount++
    }
    if (eligibleCount === 0) return
    const shouldSelect = selectedCount < eligibleCount
    setGlobalPositionSelections((prev) => {
      const next = { ...prev }
      for (const [productId] of selectedProducts) {
        const set = new Set(prev[productId] || [])
        if (shouldSelect) set.add(gpId)
        else set.delete(gpId)
        next[productId] = set
      }
      return next
    })
  }

  function togglePositionGlobal(positionName: string) {
    // Count how many products have this position name and how many have it selected
    let compatibleCount = 0
    let selectedCount = 0
    for (const [productId, product] of selectedProducts) {
      const pos = (product.render_positions ?? []).find((p) => p.name === positionName)
      if (!pos) continue
      compatibleCount++
      if (positionSelections[productId]?.has(pos.id)) selectedCount++
    }
    if (compatibleCount === 0) return
    const shouldSelect = selectedCount < compatibleCount
    setPositionSelections((prev) => {
      const next = { ...prev }
      for (const [productId, product] of selectedProducts) {
        const pos = (product.render_positions ?? []).find((p) => p.name === positionName)
        if (!pos) continue
        const set = new Set(prev[productId] || [])
        if (shouldSelect) set.add(pos.id)
        else set.delete(pos.id)
        next[productId] = set
      }
      return next
    })
  }

  // Build flat list of order lines for review (Step 3).
  // Each (product, outputType, position) triple becomes one line.
  // Global positions apply to ALL products; per-product positions are additional.
  const orderLines = useMemo(() => {
    const lines: Array<{
      key: string
      product: Product
      outputType: OutputType
      position: RenderPosition | null
      globalPosition: GlobalRenderPosition | null
    }> = []
    for (const [productId, product] of selectedProducts) {
      const selectedOts = outputSelections[productId]
      if (!selectedOts) continue
      for (const otId of selectedOts) {
        const ot = allOutputTypes?.find((o) => o.id === otId)
        if (!ot) continue

        const selectedPosIds = positionSelections[productId] || new Set()
        const selectedGlobalIds = globalPositionSelections[productId] || new Set()
        const hasAny = selectedPosIds.size > 0 || selectedGlobalIds.size > 0

        if (!hasAny) {
          // No position selected — one unpositioned line
          lines.push({ key: `${productId}-${otId}`, product, outputType: ot, position: null, globalPosition: null })
        } else {
          // One line per selected global position
          for (const gpId of selectedGlobalIds) {
            const gp = allGlobalPositions.find((g) => g.id === gpId)
            if (gp) lines.push({ key: `${productId}-${otId}-g${gpId}`, product, outputType: ot, position: null, globalPosition: gp })
          }
          // One line per selected per-product position
          for (const posId of selectedPosIds) {
            const pos = product.render_positions?.find((p) => p.id === posId)
            if (pos) lines.push({ key: `${productId}-${otId}-${posId}`, product, outputType: ot, position: pos, globalPosition: null })
          }
        }
      }
    }
    return lines
  }, [selectedProducts, outputSelections, positionSelections, globalPositionSelections, allOutputTypes, allGlobalPositions])

  function removeLine(productId: string, outputTypeId: string, positionId: string | null, globalPositionId: string | null) {
    if (positionId) {
      setPositionSelections((prev) => {
        const set = new Set(prev[productId] || [])
        set.delete(positionId)
        return { ...prev, [productId]: set }
      })
    } else if (globalPositionId) {
      setGlobalPositionSelections((prev) => {
        const set = new Set(prev[productId] || [])
        set.delete(globalPositionId)
        return { ...prev, [productId]: set }
      })
    } else {
      setOutputSelections((prev) => {
        const set = new Set(prev[productId] || [])
        set.delete(outputTypeId)
        return { ...prev, [productId]: set }
      })
    }
  }

  // Check that every selected product has at least one output type
  const allProductsHaveOutputTypes = useMemo(() => {
    for (const productId of selectedProducts.keys()) {
      const set = outputSelections[productId]
      if (!set || set.size === 0) return false
    }
    return true
  }, [selectedProducts, outputSelections])

  const totalRenderJobs = useMemo(() => {
    let count = 0
    for (const set of Object.values(outputSelections)) {
      count += set.size
    }
    return count
  }, [outputSelections])

  // Build estimate lines for pricing query
  const estimateLines = useMemo(() => {
    return orderLines.map((l) => ({
      product_id: l.product.id,
      output_type_id: l.outputType.id,
    }))
  }, [orderLines])

  const { data: priceEstimate } = useQuery({
    queryKey: ['price-estimate', estimateLines],
    queryFn: () => estimatePrice(estimateLines),
    enabled: estimateLines.length > 0 && step >= 2,
    placeholderData: keepPreviousData,
  })

  // Helper to find per-line price from estimate breakdown
  function getLinePrice(productId: string, outputTypeId: string): number | null {
    if (!priceEstimate) return null
    const match = priceEstimate.breakdown.find(
      (b) => b.product_id === productId && b.output_type_id === outputTypeId
    )
    return match?.unit_price ?? null
  }

  async function handleSubmit() {
    if (orderLines.length === 0) return
    setSubmitting(true)
    try {
      const result = await createOrder({
        notes: notes || undefined,
        lines: orderLines.map((l) => {
          const lineOv = lineOverrides[l.key]
          const override = lineOv === '__none__' ? null : (lineOv || materialOverride || null)
          return {
            product_id: l.product.id,
            output_type_id: l.outputType.id,
            render_position_id: l.position?.id ?? null,
            global_render_position_id: l.globalPosition?.id ?? null,
            material_override: override,
          }
        }),
      })
      toast.success(`Draft order ${result.order_number} created — review and submit`)
      navigate(`/orders/${result.id}`)
    } catch (e: any) {
      toast.error(e.response?.data?.detail || 'Failed to create order')
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <div className="p-8">
      {/* Header */}
      <div className="flex items-center gap-4 mb-6">
        <Link to="/orders/new" className="btn-secondary"><ArrowLeft size={16} />Back</Link>
        <h1 className="text-2xl font-bold text-content">New Product Order</h1>
      </div>

      {/* Step indicator */}
      <div className="flex items-center gap-2 mb-8">
        {[
          { n: 1, label: 'Select Products' },
          { n: 2, label: 'Configure Outputs' },
          { n: 3, label: 'Review & Submit' },
        ].map(({ n, label }, i) => (
          <div key={n} className="flex items-center gap-2">
            {i > 0 && (
              <div
                className="w-8 h-px"
                style={{ backgroundColor: step >= n ? 'var(--color-accent)' : 'var(--color-border)' }}
              />
            )}
            <div
              className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-medium ${
                step === n
                  ? 'text-white'
                  : step > n
                    ? 'bg-status-success-bg text-status-success-text'
                    : 'bg-surface-muted text-content-muted'
              }`}
              style={step === n ? { backgroundColor: 'var(--color-accent)' } : undefined}
            >
              <span className="w-5 h-5 rounded-full bg-white/20 flex items-center justify-center text-xs font-bold">
                {step > n ? <Check size={12} /> : n}
              </span>
              {label}
            </div>
          </div>
        ))}
      </div>

      {/* ================================================================ */}
      {/* STEP 1: Select Products                                          */}
      {/* ================================================================ */}
      {step === 1 && (
        <div className="pb-24">
          {/* Search + filter bar */}
          <div className="flex items-center gap-3 mb-4">
            <div className="relative flex-1">
              <Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-content-muted" />
              <input
                type="text"
                placeholder="Search by name or PIM-ID..."
                value={searchQ}
                onChange={(e) => setSearchQ(e.target.value)}
                className="w-full pl-9 pr-3 py-2 border border-border-default rounded-lg text-sm focus:outline-none focus:border-accent"
              />
            </div>
            <select
              value={categoryFilter}
              onChange={(e) => setCategoryFilter(e.target.value)}
              className="px-3 py-2 border border-border-default rounded-lg text-sm focus:outline-none focus:border-accent"
            >
              <option value="">All categories</option>
              {CATEGORIES.map((c) => (
                <option key={c.key} value={c.key}>{c.label}</option>
              ))}
            </select>
            {(products?.length ?? 0) > 0 && (
              <button
                onClick={allFilteredSelected ? deselectAllFiltered : selectAllFiltered}
                className="px-3 py-2 rounded-lg border border-border-default text-sm text-content-secondary hover:border-accent hover:text-accent transition-colors whitespace-nowrap"
                title={allFilteredSelected ? 'Deselect all currently visible products' : 'Select all currently visible products'}
              >
                {allFilteredSelected
                  ? `Deselect all (${products!.length})`
                  : `Select all (${products!.length})`}
              </button>
            )}
          </div>

          {/* Product grid */}
          {productsLoading ? (
            <div className="text-center py-12 text-content-muted">Loading products...</div>
          ) : !products?.length ? (
            <div className="text-center py-12 text-content-muted">No products with STEP files found.</div>
          ) : (
            <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
              {products.map((p) => {
                const isSelected = selectedProducts.has(p.id)
                return (
                  <div
                    key={p.id}
                    onClick={() => toggleProduct(p)}
                    className={`card cursor-pointer transition-all overflow-hidden relative ${
                      isSelected
                        ? 'ring-2 ring-accent shadow-md'
                        : 'hover:shadow-md'
                    }`}
                  >
                    {/* Selection checkbox overlay */}
                    <div
                      className={`absolute top-2 right-2 w-6 h-6 rounded-full border-2 flex items-center justify-center z-10 transition-colors ${
                        isSelected ? 'text-white' : 'bg-surface border-border-default'
                      }`}
                      style={isSelected ? { backgroundColor: 'var(--color-accent)', borderColor: 'var(--color-accent)' } : undefined}
                    >
                      {isSelected && <Check size={14} />}
                    </div>

                    {/* Thumbnail */}
                    <div className="h-32 bg-surface-muted flex items-center justify-center overflow-hidden">
                      {(p.render_image_url || p.thumbnail_url) ? (
                        <img
                          src={p.render_image_url || p.thumbnail_url!}
                          alt={p.name || p.pim_id}
                          className="h-full w-full object-contain"
                        />
                      ) : (
                        <Box size={36} className="text-content-muted" />
                      )}
                    </div>

                    {/* Info */}
                    <div className="p-3">
                      <p className="text-xs text-content-muted font-mono">{p.pim_id}</p>
                      <p className="text-sm font-medium text-content truncate">
                        {p.name || p.pim_id}
                      </p>
                      {p.category_key && (
                        <span className="inline-block mt-1 text-xs px-2 py-0.5 rounded-full bg-status-info-bg text-status-info-text">
                          {CATEGORIES.find((c) => c.key === p.category_key)?.label || p.category_key}
                        </span>
                      )}
                    </div>
                  </div>
                )
              })}
            </div>
          )}

          {/* Sticky bottom bar */}
          {selectedProducts.size > 0 && (
            <div className="fixed bottom-0 left-60 right-0 bg-surface border-t border-border-default px-8 py-4 flex items-center justify-between z-50 shadow-lg">
              <span className="text-sm font-medium text-content-secondary">
                <ShoppingCart size={16} className="inline mr-2" />
                {selectedProducts.size} product{selectedProducts.size !== 1 ? 's' : ''} selected
              </span>
              <button
                onClick={() => setStep(2)}
                className="btn-primary"
              >
                Next <ArrowRight size={16} />
              </button>
            </div>
          )}
        </div>
      )}

      {/* ================================================================ */}
      {/* STEP 2: Configure Output Types                                   */}
      {/* ================================================================ */}
      {step === 2 && (
        <div className="pb-24">
          <p className="text-sm text-content-muted mb-4">
            Select which output types to generate for each product. Only compatible types are shown.
          </p>

          {/* Global toggles — apply to all products at once */}
          {(globalOutputTypes.length > 0 || globalPositionNames.length > 0 || (anyProductUsesGlobalPositions && allGlobalPositions.length > 0)) && (
            <div className="card p-4 mb-4 space-y-3">
              <p className="text-xs font-semibold text-content-muted uppercase tracking-wide">
                Apply to all products
              </p>

              {/* Output types row */}
              {globalOutputTypes.length > 0 && (
                <div>
                  <p className="text-xs text-content-muted mb-1.5">Output Types</p>
                  <div className="flex flex-wrap gap-2">
                    {globalOutputTypes.map((ot) => {
                      let compatibleCount = 0
                      let selectedCount = 0
                      for (const [productId, product] of selectedProducts) {
                        const compatible = getCompatibleOutputTypes(product.category_key)
                        if (!compatible.some((o) => o.id === ot.id)) continue
                        compatibleCount++
                        if (outputSelections[productId]?.has(ot.id)) selectedCount++
                      }
                      const allSel = selectedCount === compatibleCount && compatibleCount > 0
                      const someSel = selectedCount > 0 && !allSel
                      return (
                        <button
                          key={ot.id}
                          onClick={() => toggleOutputTypeGlobal(ot.id)}
                          title={`${selectedCount} / ${compatibleCount} product${compatibleCount !== 1 ? 's' : ''} selected`}
                          className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full border text-sm font-medium transition-colors ${
                            allSel
                              ? 'text-white'
                              : someSel
                                ? 'bg-status-success-bg text-status-success-text border-green-400'
                                : 'bg-surface text-content-secondary border-border-default hover:border-accent hover:text-accent'
                          }`}
                          style={allSel ? { backgroundColor: 'var(--color-accent)', borderColor: 'var(--color-accent)' } : undefined}
                        >
                          {allSel && <Check size={12} />}
                          {ot.name}
                          {selectedProducts.size > 1 && (
                            <span
                              className={`text-xs ${someSel ? 'text-status-success-text' : allSel ? '' : 'text-content-muted'}`}
                              style={allSel ? { color: 'rgba(255,255,255,0.7)' } : undefined}
                            >
                              {selectedCount}/{compatibleCount}
                            </span>
                          )}
                        </button>
                      )
                    })}
                  </div>
                </div>
              )}

              {/* Perspectives row — per-product positions (for products that have them) */}
              {globalPositionNames.length > 0 && (
                <div className="pt-2 border-t border-border-light">
                  <p className="text-xs text-content-muted mb-1.5">Perspectives (custom)</p>
                  <div className="flex flex-wrap gap-2">
                    {globalPositionNames.map((posName) => {
                      let compatibleCount = 0
                      let selectedCount = 0
                      for (const [productId, product] of selectedProducts) {
                        const pos = (product.render_positions ?? []).find((p) => p.name === posName)
                        if (!pos) continue
                        compatibleCount++
                        if (positionSelections[productId]?.has(pos.id)) selectedCount++
                      }
                      const allSel = selectedCount === compatibleCount && compatibleCount > 0
                      const someSel = selectedCount > 0 && !allSel
                      return (
                        <button
                          key={posName}
                          onClick={() => togglePositionGlobal(posName)}
                          title={`${selectedCount} / ${compatibleCount} product${compatibleCount !== 1 ? 's' : ''} selected`}
                          className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full border text-sm font-medium transition-colors ${
                            allSel
                              ? 'bg-purple-600 text-white border-purple-600'
                              : someSel
                                ? 'bg-purple-100 text-purple-700 border-purple-400'
                                : 'bg-surface text-content-secondary border-border-default hover:border-purple-400 hover:text-purple-600'
                          }`}
                        >
                          {allSel && <Check size={12} />}
                          {posName}
                          {selectedProducts.size > 1 && (
                            <span className={`text-xs ${allSel ? 'text-white/70' : someSel ? 'text-purple-500' : 'text-content-muted'}`}>
                              {selectedCount}/{compatibleCount}
                            </span>
                          )}
                        </button>
                      )
                    })}
                  </div>
                </div>
              )}

              {/* Perspectives row — global positions (for products without custom positions) */}
              {anyProductUsesGlobalPositions && allGlobalPositions.length > 0 && (
                <div className="pt-2 border-t border-border-light">
                  <p className="text-xs text-content-muted mb-1.5">Perspectives (global)</p>
                  <div className="flex flex-wrap gap-2">
                    {allGlobalPositions.map((gp) => {
                      const eligibleCount = selectedProducts.size
                      let selectedCount = 0
                      for (const [productId] of selectedProducts) {
                        if (globalPositionSelections[productId]?.has(gp.id)) selectedCount++
                      }
                      const allSel = selectedCount === eligibleCount && eligibleCount > 0
                      const someSel = selectedCount > 0 && !allSel
                      return (
                        <button
                          key={gp.id}
                          onClick={() => toggleGlobalPositionForAll(gp.id)}
                          title={`${selectedCount} / ${eligibleCount} product${eligibleCount !== 1 ? 's' : ''} selected`}
                          className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full border text-sm font-medium transition-colors ${
                            allSel
                              ? 'bg-purple-600 text-white border-purple-600'
                              : someSel
                                ? 'bg-purple-100 text-purple-700 border-purple-400'
                                : 'bg-surface text-content-secondary border-border-default hover:border-purple-400 hover:text-purple-600'
                          }`}
                        >
                          {allSel && <Check size={12} />}
                          {gp.name}
                          {gp.is_default && !allSel && <span className="text-xs opacity-60">★</span>}
                          {selectedProducts.size > 1 && eligibleCount > 0 && (
                            <span className={`text-xs ${allSel ? 'text-white/70' : someSel ? 'text-purple-500' : 'text-content-muted'}`}>
                              {selectedCount}/{eligibleCount}
                            </span>
                          )}
                        </button>
                      )
                    })}
                  </div>
                </div>
              )}
            </div>
          )}

          <div className="space-y-3">
            {Array.from(selectedProducts.values()).map((product) => (
              <ProductOutputRow
                key={product.id}
                product={product}
                compatibleTypes={getCompatibleOutputTypes(product.category_key)}
                selected={outputSelections[product.id] || new Set()}
                onToggle={(otId) => toggleOutputType(product.id, otId)}
                selectedPositions={positionSelections[product.id] || new Set()}
                onTogglePosition={(posId) => togglePosition(product.id, posId)}
                globalPositions={allGlobalPositions}
                selectedGlobalPositions={globalPositionSelections[product.id] || new Set()}
                onToggleGlobalPosition={(gpId) => setGlobalPositionSelections((prev) => {
                  const set = new Set(prev[product.id] || [])
                  if (set.has(gpId)) set.delete(gpId); else set.add(gpId)
                  return { ...prev, [product.id]: set }
                })}
              />
            ))}
          </div>

          {/* Bottom bar */}
          <div className="fixed bottom-0 left-60 right-0 bg-surface border-t border-border-default px-8 py-4 flex items-center justify-between z-50 shadow-lg">
            <div className="flex items-center gap-4">
              <button onClick={() => setStep(1)} className="btn-secondary">
                <ArrowLeft size={16} /> Back
              </button>
              <span className="text-sm text-content-muted">
                {selectedProducts.size} product{selectedProducts.size !== 1 ? 's' : ''} &middot; {orderLines.length} render job{orderLines.length !== 1 ? 's' : ''}
                {priceEstimate && priceEstimate.total > 0 && (
                  <> &middot; Estimated: <span className="font-semibold text-content-secondary">{formatCurrency(priceEstimate.total)}</span></>
                )}
              </span>
            </div>
            <button
              onClick={() => setStep(3)}
              disabled={!allProductsHaveOutputTypes}
              className="btn-primary disabled:opacity-40 disabled:cursor-not-allowed"
            >
              Next <ArrowRight size={16} />
            </button>
          </div>
        </div>
      )}

      {/* ================================================================ */}
      {/* STEP 3: Review & Submit                                          */}
      {/* ================================================================ */}
      {step === 3 && (
        <div className="pb-24">
          {orderLines.length === 0 ? (
            <div className="card p-8 text-center text-content-muted">
              No render jobs configured. Go back and select output types.
            </div>
          ) : (
            <>
              <div className="card overflow-hidden mb-4">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-border-default bg-surface-alt text-left">
                      <th className="px-4 py-3 font-medium text-content-secondary">Product</th>
                      <th className="px-4 py-3 font-medium text-content-secondary">Output Type</th>
                      <th className="px-4 py-3 font-medium text-content-secondary">Position</th>
                      <th className="px-4 py-3 font-medium text-content-secondary">Renderer</th>
                      <th className="px-4 py-3 font-medium text-content-secondary">Format</th>
                      <th className="px-4 py-3 font-medium text-content-secondary">Mat Override</th>
                      <th className="px-4 py-3 font-medium text-content-secondary text-right">Price</th>
                      <th className="px-4 py-3 font-medium text-content-secondary w-12"></th>
                    </tr>
                  </thead>
                  <tbody>
                    {orderLines.map((line) => (
                      <tr key={line.key} className="border-b border-border-light hover:bg-surface-hover">
                        <td className="px-4 py-3">
                          <div className="flex items-center gap-3">
                            <div className="w-10 h-10 rounded bg-surface-muted flex items-center justify-center overflow-hidden shrink-0">
                              {(line.product.render_image_url || line.product.thumbnail_url) ? (
                                <img src={line.product.render_image_url || line.product.thumbnail_url!} className="w-full h-full object-contain" />
                              ) : (
                                <Box size={18} className="text-content-muted" />
                              )}
                            </div>
                            <div className="min-w-0">
                              <p className="font-medium text-content truncate">
                                {line.product.name || line.product.pim_id}
                              </p>
                              <span className="text-xs text-content-muted font-mono">{line.product.pim_id}</span>
                            </div>
                          </div>
                        </td>
                        <td className="px-4 py-3 text-content-secondary">{line.outputType.name}</td>
                        <td className="px-4 py-3">
                          {line.position ? (
                            <span className="badge-purple">{line.position.name}</span>
                          ) : line.globalPosition ? (
                            <span className="badge-purple opacity-70" title="Global position">{line.globalPosition.name}</span>
                          ) : (
                            <span className="text-content-muted text-xs">—</span>
                          )}
                        </td>
                        <td className="px-4 py-3 text-content-muted">{line.outputType.renderer}</td>
                        <td className="px-4 py-3 text-content-muted uppercase">{line.outputType.output_format}</td>
                        <td className="px-4 py-3">
                          <select
                            className="text-xs border border-border-default rounded px-1.5 py-1 w-full"
                            style={{ backgroundColor: (lineOverrides[line.key] || materialOverride) ? 'rgba(245, 158, 11, 0.1)' : 'var(--color-bg-surface)' }}
                            value={lineOverrides[line.key] ?? ''}
                            onChange={(e) => setLineOverrides((prev) => ({ ...prev, [line.key]: e.target.value }))}
                          >
                            <option value="">{materialOverride ? `Global: ${materialOverride.replace('HARTOMAT_', '').replace(/_/g, ' ')}` : 'No override'}</option>
                            {materialOverride && <option value="__none__">— No override (clear) —</option>}
                            {libMaterials.map((m: Material) => (
                              <option key={m.id} value={m.name}>{m.name.replace('HARTOMAT_', '').replace(/_/g, ' ')}</option>
                            ))}
                          </select>
                        </td>
                        <td className="px-4 py-3 text-right">
                          {(() => {
                            const price = getLinePrice(line.product.id, line.outputType.id)
                            return price != null ? (
                              <span className="font-medium text-content-secondary">{formatCurrency(price)}</span>
                            ) : (
                              <span className="text-content-muted">—</span>
                            )
                          })()}
                        </td>
                        <td className="px-4 py-3">
                          <button
                            onClick={() => removeLine(line.product.id, line.outputType.id, line.position?.id ?? null, line.globalPosition?.id ?? null)}
                            className="text-content-muted hover:text-red-500 transition-colors"
                            title="Remove this render job from the order"
                          >
                            <Trash2 size={15} />
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>

              {/* Material Override */}
              <div className="card p-4 mb-4">
                <label className="block text-sm font-medium text-content-secondary mb-1">
                  Material Override (optional)
                </label>
                <p className="text-xs text-content-muted mb-2">
                  Apply a single material to all parts of all products in this order. Leave empty to use each product's own materials.
                </p>
                <select
                  value={materialOverride}
                  onChange={(e) => setMaterialOverride(e.target.value)}
                  className="w-full max-w-md px-3 py-2 border border-border-default rounded-lg text-sm focus:outline-none focus:border-accent"
                  style={{ backgroundColor: materialOverride ? 'rgba(245, 158, 11, 0.1)' : 'var(--color-bg-surface)' }}
                >
                  <option value="">No material override</option>
                  {libMaterials.map((m: Material) => (
                    <option key={m.id} value={m.name}>{m.name}</option>
                  ))}
                </select>
              </div>

              {/* Notes */}
              <div className="card p-4 mb-4">
                <label className="block text-sm font-medium text-content-secondary mb-1">
                  Order Notes (optional)
                </label>
                <textarea
                  value={notes}
                  onChange={(e) => setNotes(e.target.value)}
                  placeholder="Any special instructions..."
                  rows={3}
                  className="w-full px-3 py-2 border border-border-default rounded-lg text-sm focus:outline-none focus:border-accent resize-none"
                />
              </div>
            </>
          )}

          {/* Bottom bar */}
          <div className="fixed bottom-0 left-60 right-0 bg-surface border-t border-border-default px-8 py-4 flex items-center justify-between z-50 shadow-lg">
            <button onClick={() => setStep(2)} className="btn-secondary">
              <ArrowLeft size={16} /> Back
            </button>
            <div className="flex items-center gap-3">
              <span className="text-sm text-content-muted">
                {orderLines.length} render job{orderLines.length !== 1 ? 's' : ''}
                {priceEstimate && priceEstimate.total > 0 && (
                  <> &middot; Estimated: <span className="font-semibold text-content-secondary">{formatCurrency(priceEstimate.total)}</span></>
                )}
              </span>
              <button
                onClick={handleSubmit}
                disabled={submitting || orderLines.length === 0}
                className="btn-primary disabled:opacity-40 disabled:cursor-not-allowed"
              >
                {submitting ? 'Creating...' : 'Create Order'}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}

// ---- Sub-component: expandable product row for step 2 ----

function ProductOutputRow({
  product,
  compatibleTypes,
  selected,
  onToggle,
  selectedPositions,
  onTogglePosition,
  globalPositions,
  selectedGlobalPositions,
  onToggleGlobalPosition,
}: {
  product: Product
  compatibleTypes: OutputType[]
  selected: Set<string>
  onToggle: (otId: string) => void
  selectedPositions: Set<string>
  onTogglePosition: (posId: string) => void
  globalPositions: GlobalRenderPosition[]
  selectedGlobalPositions: Set<string>
  onToggleGlobalPosition: (gpId: string) => void
}) {
  const [expanded, setExpanded] = useState(true)

  return (
    <div className="card overflow-hidden">
      {/* Header row */}
      <div
        className="flex items-center gap-3 px-4 py-3 cursor-pointer hover:bg-surface-hover"
        onClick={() => setExpanded(!expanded)}
      >
        {expanded ? <ChevronDown size={16} className="text-content-muted" /> : <ChevronRight size={16} className="text-content-muted" />}
        <div className="w-10 h-10 rounded bg-surface-muted flex items-center justify-center overflow-hidden shrink-0">
          {(product.render_image_url || product.thumbnail_url) ? (
            <img src={product.render_image_url || product.thumbnail_url!} className="w-full h-full object-contain" />
          ) : (
            <Box size={18} className="text-content-muted" />
          )}
        </div>
        <div className="flex-1 min-w-0">
          <p className="text-sm font-medium text-content truncate">
            {product.name || product.pim_id}
          </p>
          <div className="flex items-center gap-2">
            <span className="text-xs text-content-muted font-mono">{product.pim_id}</span>
            {product.category_key && (
              <span className="text-xs px-2 py-0.5 rounded-full bg-status-info-bg text-status-info-text">
                {product.category_key}
              </span>
            )}
          </div>
        </div>
        <span className="text-xs text-content-muted">
          {selected.size} selected
        </span>
      </div>

      {/* Output type checkboxes */}
      {expanded && (
        <div className="px-4 pb-4 pt-1 border-t border-border-light">
          {compatibleTypes.length === 0 ? (
            <p className="text-sm text-content-muted py-2">No compatible output types found.</p>
          ) : (
            <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2 mt-2">
              {compatibleTypes.map((ot) => {
                const checked = selected.has(ot.id)
                return (
                  <label
                    key={ot.id}
                    className={`flex items-center gap-3 px-3 py-2.5 rounded-lg border cursor-pointer transition-colors ${
                      checked ? '' : 'border-border-default'
                    }`}
                    style={checked ? { borderColor: 'var(--color-accent)', backgroundColor: 'var(--color-accent-light)' } : undefined}
                  >
                    <input
                      type="checkbox"
                      checked={checked}
                      onChange={() => onToggle(ot.id)}
                      className=""
                    />
                    <div className="min-w-0 flex-1">
                      <p className="text-sm font-medium text-content">{ot.name}</p>
                      <p className="text-xs text-content-muted">
                        {ot.renderer} &middot; {ot.output_format.toUpperCase()}
                        {ot.price_per_item != null && (
                          <> &middot; <span className="text-emerald-600 font-medium">{formatCurrency(ot.price_per_item)}</span></>
                        )}
                      </p>
                    </div>
                  </label>
                )
              })}
            </div>
          )}

          {/* Per-product custom positions */}
          {(product.render_positions?.length ?? 0) > 0 && (
            <div className="mt-3 pt-3 border-t border-border-light">
              <div className="flex items-center gap-2 mb-2">
                <p className="text-xs font-medium text-content-muted">Custom Positions</p>
                <button
                  className="text-xs text-accent hover:underline"
                  onClick={() => product.render_positions!.forEach((p) => !selectedPositions.has(p.id) && onTogglePosition(p.id))}
                >
                  All
                </button>
                <span className="text-content-muted text-xs">·</span>
                <button
                  className="text-xs text-content-muted hover:underline"
                  onClick={() => product.render_positions!.forEach((p) => selectedPositions.has(p.id) && onTogglePosition(p.id))}
                >
                  None
                </button>
              </div>
              <div className="flex flex-wrap gap-2">
                {product.render_positions!.map((pos) => {
                  const active = selectedPositions.has(pos.id)
                  return (
                    <button
                      key={pos.id}
                      onClick={() => onTogglePosition(pos.id)}
                      className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full border text-sm font-medium transition-colors ${
                        active
                          ? 'bg-purple-600 text-white border-purple-600'
                          : 'bg-surface text-content-secondary border-border-default hover:border-purple-400 hover:text-purple-600'
                      }`}
                    >
                      {active && <Check size={12} />}
                      {pos.name}
                      {pos.is_default && !active && (
                        <span className="text-xs text-content-muted">(default)</span>
                      )}
                    </button>
                  )
                })}
              </div>
            </div>
          )}

          {/* Global position toggles — always shown for all products */}
          {globalPositions.length > 0 && (
            <div className="mt-3 pt-3 border-t border-border-light">
              <div className="flex items-center gap-2 mb-2">
                <p className="text-xs font-medium text-content-muted">Perspectives</p>
                <button
                  className="text-xs text-accent hover:underline"
                  onClick={() => globalPositions.forEach((g) => !selectedGlobalPositions.has(g.id) && onToggleGlobalPosition(g.id))}
                >
                  All
                </button>
                <span className="text-content-muted text-xs">·</span>
                <button
                  className="text-xs text-content-muted hover:underline"
                  onClick={() => globalPositions.forEach((g) => selectedGlobalPositions.has(g.id) && onToggleGlobalPosition(g.id))}
                >
                  None
                </button>
              </div>
              <div className="flex flex-wrap gap-2">
                {globalPositions.map((gp) => {
                  const active = selectedGlobalPositions.has(gp.id)
                  return (
                    <button
                      key={gp.id}
                      onClick={() => onToggleGlobalPosition(gp.id)}
                      className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full border text-sm font-medium transition-colors ${
                        active
                          ? 'bg-purple-600 text-white border-purple-600'
                          : 'bg-surface text-content-secondary border-border-default hover:border-purple-400 hover:text-purple-600'
                      }`}
                    >
                      {active && <Check size={12} />}
                      {gp.name}
                      {gp.is_default && <span className="text-xs opacity-60 ml-0.5">★</span>}
                    </button>
                  )
                })}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  )
}
