import { useState, useRef, useMemo } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { Trash2, Plus, List, Layers } from 'lucide-react'
import {
  fetchShopping,
  addCustomItem,
  toggleCheck,
  deleteItem,
  deleteChecked,
  deleteAll,
} from '../api/shopping'
import type { ShoppingItem } from '../api/shopping'
import { useAuth } from '../context/AuthContext'
import { EmptyState } from '../components/ui/EmptyState'

// Merged item for combined view
interface MergedItem {
  key: string
  name: string
  totalAmount: number | null
  unit: string | null
  items: ShoppingItem[] // original items that were merged
  allChecked: boolean
  someChecked: boolean
  recipes: string[] // recipe names
}

function mergeItems(groups: { recipe_title: string; recipe_id?: string; items: ShoppingItem[] }[]): MergedItem[] {
  const allItems = groups.flatMap((g) =>
    g.items.map((item) => ({ ...item, recipe_title: g.recipe_title, recipe_id: g.recipe_id }))
  )

  const merged = new Map<string, MergedItem>()

  for (const item of allItems) {
    const normalizedName = item.name.trim().toLowerCase()
    const normalizedUnit = (item.unit || '').trim().toLowerCase()
    const key = `${normalizedName}::${normalizedUnit}`

    if (merged.has(key)) {
      const existing = merged.get(key)!
      existing.items.push(item)
      if (item.amount != null && existing.totalAmount != null) {
        existing.totalAmount += item.amount
      } else if (item.amount != null) {
        existing.totalAmount = item.amount
      }
      if (item.recipe_title && !existing.recipes.includes(item.recipe_title)) {
        existing.recipes.push(item.recipe_title)
      }
      existing.allChecked = existing.items.every((i) => i.checked)
      existing.someChecked = existing.items.some((i) => i.checked)
    } else {
      merged.set(key, {
        key,
        name: item.name, // keep original casing from first occurrence
        totalAmount: item.amount ?? null,
        unit: item.unit || null,
        items: [item],
        allChecked: !!item.checked,
        someChecked: !!item.checked,
        recipes: item.recipe_title ? [item.recipe_title] : [],
      })
    }
  }

  // Sort: unchecked first, then by name
  return Array.from(merged.values()).sort((a, b) => {
    if (a.allChecked !== b.allChecked) return a.allChecked ? 1 : -1
    return a.name.localeCompare(b.name, 'de')
  })
}

export function ShoppingPage() {
  const qc = useQueryClient()
  const { isAuthenticated, isLoading: authLoading } = useAuth()
  const [newItem, setNewItem] = useState('')
  const [scope, setScope] = useState<'personal' | 'household'>('personal')
  const [viewMode, setViewMode] = useState<'recipe' | 'merged'>('merged')
  const inputRef = useRef<HTMLInputElement>(null)

  const { data: householdData } = useQuery({
    queryKey: ['household'],
    queryFn: async () => {
      const { getMyHousehold } = await import('../api/households')
      try {
        const res = await getMyHousehold()
        return res.data
      } catch {
        return null
      }
    },
    enabled: isAuthenticated,
    retry: false,
  })
  const hasHousehold = !!householdData

  const activeScope = hasHousehold ? scope : undefined

    const { data: groups = [], isLoading, refetch } = useQuery({
    queryKey: ['shopping', activeScope],
    queryFn: () => fetchShopping(activeScope),
    enabled: isAuthenticated,
  })

  const mergedItems = useMemo(() => mergeItems(groups), [groups])

  const checkMutation = useMutation({
    mutationFn: toggleCheck,
    onSuccess: () => qc.invalidateQueries({ queryKey: ['shopping'] }),
  })

  const deleteMutation = useMutation({
    mutationFn: deleteItem,
    onSuccess: () => qc.invalidateQueries({ queryKey: ['shopping'] }),
  })

  const deleteCheckedMutation = useMutation({
    mutationFn: () => deleteChecked(activeScope),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['shopping'] }),
  })

  const deleteAllMutation = useMutation({
    mutationFn: () => deleteAll(activeScope),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['shopping'] }),
  })

  const [showClearConfirm, setShowClearConfirm] = useState(false)

  const addMutation = useMutation({
    mutationFn: (item: { name: string }) => addCustomItem(item, activeScope),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['shopping'] })
      setNewItem('')
      inputRef.current?.focus()
    },
  })

  const handleAdd = () => {
    const name = newItem.trim()
    if (!name) return
    addMutation.mutate({ name })
  }

  // Toggle all items in a merged group
  const handleMergedToggle = async (merged: MergedItem) => {
    // If all checked → uncheck all, otherwise check all unchecked
    const itemsToToggle = merged.allChecked
      ? merged.items
      : merged.items.filter((i) => !i.checked)
    for (const item of itemsToToggle) {
      checkMutation.mutate(item.id)
    }
  }

  // Delete all items in a merged group
  const handleMergedDelete = async (merged: MergedItem) => {
    for (const item of merged.items) {
      deleteMutation.mutate(item.id)
    }
  }

  const hasChecked = groups.some((g) => g.items.some((i) => i.checked))
  const totalItems = groups.reduce((acc, g) => acc + g.items.length, 0)
  const totalChecked = groups.reduce((acc, g) => acc + g.items.filter((i) => i.checked).length, 0)
  const totalUnchecked = totalItems - totalChecked
  const recipeCount = groups.filter((g) => g.recipe_id).length

  const sortItems = (items: ShoppingItem[]) => {
    const unchecked = items.filter((i) => !i.checked)
    const checked = items.filter((i) => i.checked)
    return [...unchecked, ...checked]
  }

  const [pulling, setPulling] = useState(false)
  const touchStartY = useRef(0)

  const handleTouchStart = (e: React.TouchEvent) => {
    if (window.scrollY === 0) touchStartY.current = e.touches[0].clientY
  }

  const handleTouchEnd = (e: React.TouchEvent) => {
    if (pulling) {
      const dy = e.changedTouches[0].clientY - touchStartY.current
      if (dy > 80) refetch()
      setPulling(false)
    }
  }

  const handleTouchMove = (e: React.TouchEvent) => {
    if (window.scrollY === 0) {
      const dy = e.touches[0].clientY - touchStartY.current
      if (dy > 30) setPulling(true)
    }
  }

  if (!authLoading && !isAuthenticated) {
    return (
      <div className="min-h-screen flex flex-col items-center justify-center px-4">
        <div className="text-center">
          <div className="text-6xl mb-4">🛒</div>
          <h2 className="font-display text-2xl text-espresso mb-2">Einkaufsliste</h2>
          <p className="text-warm-grey mb-6">
            Melde dich an, um deine eigene Einkaufsliste zu nutzen und sie mit deinem Haushalt zu teilen.
          </p>
          <div className="space-y-3 w-full max-w-sm mx-auto">
            <a href="/login" className="block w-full bg-primary text-white rounded-xl py-3 font-medium min-h-[44px] text-center">
              Anmelden
            </a>
            <a href="/register" className="block w-full border border-sand text-espresso rounded-xl py-3 font-medium min-h-[44px] text-center">
              Registrieren
            </a>
          </div>
        </div>
      </div>
    )
  }

  if (isLoading || authLoading) {
    return (
      <div className="p-4 space-y-4">
        {[1, 2, 3].map((i) => (
          <div key={i} className="bg-surface rounded-2xl p-4 animate-pulse h-20" />
        ))}
      </div>
    )
  }

  return (
    <div
      className="min-h-screen"
      onTouchStart={handleTouchStart}
      onTouchMove={handleTouchMove}
      onTouchEnd={handleTouchEnd}
    >
      {/* TopBar */}
      <div className="sticky top-0 z-40 bg-cream/95 backdrop-blur-sm border-b border-sand px-4 py-3 flex items-center justify-between">
        <h1 className="font-display text-xl text-espresso">Einkaufsliste</h1>
        <div className="flex items-center gap-1">
          {/* View toggle */}
          <button
            onClick={() => setViewMode(viewMode === 'merged' ? 'recipe' : 'merged')}
            className="p-2 text-warm-grey hover:text-primary transition-colors min-w-[44px] min-h-[44px] flex items-center justify-center"
            title={viewMode === 'merged' ? 'Nach Rezept anzeigen' : 'Zusammengefasst anzeigen'}
          >
            {viewMode === 'merged' ? <List size={18} /> : <Layers size={18} />}
          </button>
          {totalUnchecked > 0 && (
            <span className="text-sm text-warm-grey">{totalUnchecked}</span>
          )}
          {hasChecked && (
            <button
              onClick={() => deleteCheckedMutation.mutate()}
              className="p-2 text-warm-grey hover:text-berry-red transition-colors min-w-[44px] min-h-[44px] flex items-center justify-center"
              title="Erledigte löschen"
            >
              <Trash2 size={18} />
            </button>
          )}
          {totalItems > 0 && (
            <button
              onClick={() => setShowClearConfirm(true)}
              className="p-2 text-warm-grey hover:text-berry-red transition-colors min-w-[44px] min-h-[44px] flex items-center justify-center"
              title="Alles löschen"
            >
              <Trash2 size={20} className="text-berry-red/70" />
            </button>
          )}
        </div>
      </div>

      {/* Scope Toggle */}
      {hasHousehold && (
        <div className="sticky top-[53px] z-35 bg-cream/95 backdrop-blur-sm px-4 py-2">
          <div className="flex bg-sand/50 rounded-xl p-1">
            <button
              onClick={() => setScope('personal')}
              className={`flex-1 py-2 rounded-lg text-sm font-medium transition-colors min-h-[36px] ${
                scope === 'personal' ? 'bg-primary text-white' : 'text-warm-grey hover:text-espresso'
              }`}
            >
              Persönlich
            </button>
            <button
              onClick={() => setScope('household')}
              className={`flex-1 py-2 rounded-lg text-sm font-medium transition-colors min-h-[36px] ${
                scope === 'household' ? 'bg-primary text-white' : 'text-warm-grey hover:text-espresso'
              }`}
            >
              🏠 Haushalt
            </button>
          </div>
        </div>
      )}

      {/* Clear All Confirm */}
      {showClearConfirm && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 backdrop-blur-sm px-6">
          <div className="bg-surface rounded-2xl p-6 max-w-sm w-full shadow-xl">
            <h3 className="font-display text-lg text-espresso mb-2">Einkaufsliste leeren?</h3>
            <p className="text-warm-grey text-sm mb-5">Alle Artikel werden unwiderruflich gelöscht.</p>
            <div className="flex gap-3">
              <button
                onClick={() => setShowClearConfirm(false)}
                className="flex-1 py-3 rounded-xl border border-sand text-espresso font-medium min-h-[44px]"
              >
                Abbrechen
              </button>
              <button
                onClick={() => { deleteAllMutation.mutate(); setShowClearConfirm(false) }}
                className="flex-1 py-3 rounded-xl bg-berry-red text-white font-medium min-h-[44px]"
              >
                🗑️ Alles löschen
              </button>
            </div>
          </div>
        </div>
      )}

      {pulling && (
        <div className="text-center text-warm-grey text-sm py-2">↓ Loslassen zum Aktualisieren</div>
      )}

      {/* Quick-Add */}
      <div className={`sticky ${hasHousehold ? 'top-[105px]' : 'top-[53px]'} z-30 bg-cream/95 backdrop-blur-sm px-4 py-3`}>
        <form onSubmit={(e) => { e.preventDefault(); handleAdd() }} className="flex gap-2">
          <input
            ref={inputRef}
            type="text"
            value={newItem}
            onChange={(e) => setNewItem(e.target.value)}
            placeholder="Artikel hinzufügen..."
            className="flex-1 bg-surface border border-sand rounded-xl px-4 py-3 text-base sm:text-lg text-espresso placeholder:text-warm-grey/50 focus:outline-none focus:ring-2 focus:ring-primary/30"
          />
          <button
            type="submit"
            disabled={!newItem.trim() || addMutation.isPending}
            className="bg-primary text-white rounded-xl px-4 py-3 min-w-[44px] min-h-[44px] flex items-center justify-center disabled:opacity-40 transition-opacity"
          >
            <Plus size={20} />
          </button>
        </form>
      </div>

      {/* Summary */}
      {totalItems > 0 && (
        <div className="px-4 pb-2">
          <div className="bg-primary-light/30 rounded-2xl p-3">
            <div className="flex items-center justify-between text-sm text-espresso">
              <span>
                {viewMode === 'merged'
                  ? <>{mergedItems.length} Artikel{mergedItems.length !== 1 ? '' : ''} · {totalChecked} erledigt</>
                  : <>{recipeCount > 0 && <>{recipeCount} Rezept{recipeCount !== 1 ? 'e' : ''} · </>}{totalItems} Artikel · {totalChecked} erledigt</>
                }
              </span>
              <span className="text-warm-grey text-xs">
                {totalItems > 0 ? Math.round((totalChecked / totalItems) * 100) : 0}%
              </span>
            </div>
            <div className="mt-2 h-1.5 bg-sand rounded-full overflow-hidden">
              <div
                className="h-full bg-primary rounded-full transition-all duration-300"
                style={{ width: `${totalItems > 0 ? (totalChecked / totalItems) * 100 : 0}%` }}
              />
            </div>
          </div>
        </div>
      )}

      {/* Content */}
      <div className="px-4 pb-24 space-y-4">
        {groups.length === 0 ? (
          <EmptyState
            icon="🛒"
            title="Einkaufsliste leer"
            description="Füge Zutaten aus einem Rezept hinzu oder erstelle eigene Einträge."
          />
        ) : viewMode === 'merged' ? (
          /* ── Merged/Combined View ── */
          <div className="bg-surface rounded-2xl shadow-sm overflow-hidden">
            <div className="px-4 py-3 border-b border-sand/50 flex items-center gap-2">
              <span className="text-base">🛒</span>
              <h3 className="font-semibold text-sm text-espresso">Zusammengefasst</h3>
              <span className="text-xs text-warm-grey ml-auto">
                {mergedItems.filter((m) => !m.allChecked).length}/{mergedItems.length}
              </span>
            </div>
            <ul>
              {mergedItems.map((merged) => (
                <MergedItemRow
                  key={merged.key}
                  merged={merged}
                  onToggle={() => handleMergedToggle(merged)}
                  onDelete={() => handleMergedDelete(merged)}
                />
              ))}
            </ul>
          </div>
        ) : (
          /* ── Recipe-grouped View ── */
          groups.map((group) => (
            <div key={group.recipe_title} className="bg-surface rounded-2xl shadow-sm overflow-hidden">
              <div className="px-4 py-3 border-b border-sand/50 flex items-center gap-2">
                <span className="text-base">{group.recipe_id ? '🍰' : '📝'}</span>
                <h3 className="font-semibold text-sm text-espresso truncate">
                  {group.recipe_title || 'Eigene'}
                </h3>
                <span className="text-xs text-warm-grey ml-auto">
                  {group.items.filter((i) => !i.checked).length}/{group.items.length}
                </span>
              </div>
              <ul>
                {sortItems(group.items).map((item) => (
                  <ShoppingItemRow
                    key={item.id}
                    item={item}
                    onToggle={() => checkMutation.mutate(item.id)}
                    onDelete={() => deleteMutation.mutate(item.id)}
                  />
                ))}
              </ul>
            </div>
          ))
        )}
      </div>
    </div>
  )
}

/* ── Merged Item Row ── */
function MergedItemRow({
  merged,
  onToggle,
  onDelete,
}: {
  merged: MergedItem
  onToggle: () => void
  onDelete: () => void
}) {
  const THRESHOLD = -80
  const [swipeX, setSwipeX] = useState(0)
  const touchStartX = useRef(0)
  const swiping = useRef(false)
  const pastThreshold = swipeX < THRESHOLD

  const handleTouchStart = (e: React.TouchEvent) => {
    touchStartX.current = e.touches[0].clientX
    swiping.current = false
  }

  const handleTouchMove = (e: React.TouchEvent) => {
    const dx = e.touches[0].clientX - touchStartX.current
    if (dx < -10) {
      swiping.current = true
      setSwipeX(Math.max(dx, -160))
    } else {
      setSwipeX(0)
    }
  }

  const handleTouchEnd = () => {
    if (pastThreshold) {
      setSwipeX(-300)
      setTimeout(() => onDelete(), 200)
    } else {
      setSwipeX(0)
    }
    swiping.current = false
  }

  const amountText = [
    merged.totalAmount != null ? (Number.isInteger(merged.totalAmount) ? merged.totalAmount : merged.totalAmount.toFixed(1)) : null,
    merged.unit,
  ].filter(Boolean).join(' ')

  const isChecked = merged.allChecked

  return (
    <li className="relative overflow-hidden">
      <div className={`absolute inset-y-0 right-0 w-40 flex items-center justify-center transition-colors ${pastThreshold ? 'bg-berry-red' : 'bg-berry-red/60'}`}>
        <span className={`text-white font-medium transition-all ${pastThreshold ? 'text-sm scale-110' : 'text-xs'}`}>
          {pastThreshold ? '🗑️ Löschen' : '×'}
        </span>
      </div>

      <div
        className={`relative bg-surface flex items-center gap-3 px-4 min-h-[52px] ${swiping.current ? '' : 'transition-transform duration-200'}`}
        style={{ transform: `translateX(${swipeX}px)` }}
        onTouchStart={handleTouchStart}
        onTouchMove={handleTouchMove}
        onTouchEnd={handleTouchEnd}
      >
        <button
          onClick={onToggle}
          className="flex-shrink-0 w-6 h-6 rounded-md border-2 flex items-center justify-center transition-colors min-w-[44px] min-h-[44px]"
          style={{
            borderColor: isChecked ? '#C4737E' : merged.someChecked ? '#C4737E80' : '#E8E0D8',
            backgroundColor: isChecked ? '#C4737E' : 'transparent',
          }}
        >
          {isChecked && (
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
              <path d="M2.5 7L5.5 10L11.5 4" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          )}
          {merged.someChecked && !isChecked && (
            <div className="w-2 h-2 rounded-sm bg-primary/60" />
          )}
        </button>

        <div className={`flex-1 min-w-0 ${isChecked ? 'opacity-50' : ''}`}>
          <span className={`text-base sm:text-lg text-espresso ${isChecked ? 'line-through text-warm-grey' : ''}`}>
            {merged.name}
          </span>
          {merged.items.length > 1 && (
            <p className="text-xs text-warm-grey truncate">
              {merged.recipes.length > 0 ? merged.recipes.join(', ') : `${merged.items.length}×`}
            </p>
          )}
        </div>

        {amountText && (
          <span className={`text-sm flex-shrink-0 font-medium ${isChecked ? 'text-warm-grey/50 line-through' : 'text-warm-grey'}`}>
            {amountText}
          </span>
        )}

        {merged.items.length > 1 && !isChecked && (
          <span className="text-xs bg-primary/10 text-primary px-1.5 py-0.5 rounded-full flex-shrink-0">
            {merged.items.length}×
          </span>
        )}
      </div>
    </li>
  )
}

/* ── Single Item Row ── */
function ShoppingItemRow({
  item,
  onToggle,
  onDelete,
}: {
  item: ShoppingItem
  onToggle: () => void
  onDelete: () => void
}) {
  const THRESHOLD = -80
  const [swipeX, setSwipeX] = useState(0)
  const touchStartX = useRef(0)
  const swiping = useRef(false)
  const pastThreshold = swipeX < THRESHOLD

  const handleTouchStart = (e: React.TouchEvent) => {
    touchStartX.current = e.touches[0].clientX
    swiping.current = false
  }

  const handleTouchMove = (e: React.TouchEvent) => {
    const dx = e.touches[0].clientX - touchStartX.current
    if (dx < -10) {
      swiping.current = true
      setSwipeX(Math.max(dx, -160))
    } else {
      setSwipeX(0)
    }
  }

  const handleTouchEnd = () => {
    if (pastThreshold) {
      setSwipeX(-300)
      setTimeout(() => onDelete(), 200)
    } else {
      setSwipeX(0)
    }
    swiping.current = false
  }

  const amountText = [item.amount, item.unit].filter(Boolean).join(' ')

  return (
    <li className="relative overflow-hidden">
      <div className={`absolute inset-y-0 right-0 w-40 flex items-center justify-center transition-colors ${pastThreshold ? 'bg-berry-red' : 'bg-berry-red/60'}`}>
        <span className={`text-white font-medium transition-all ${pastThreshold ? 'text-sm scale-110' : 'text-xs'}`}>
          {pastThreshold ? '🗑️ Löschen' : '×'}
        </span>
      </div>

      <div
        className={`relative bg-surface flex items-center gap-3 px-4 min-h-[52px] ${swiping.current ? '' : 'transition-transform duration-200'}`}
        style={{ transform: `translateX(${swipeX}px)` }}
        onTouchStart={handleTouchStart}
        onTouchMove={handleTouchMove}
        onTouchEnd={handleTouchEnd}
      >
        <button
          onClick={onToggle}
          className="flex-shrink-0 w-6 h-6 rounded-md border-2 flex items-center justify-center transition-colors min-w-[44px] min-h-[44px]"
          style={{
            borderColor: item.checked ? '#C4737E' : '#E8E0D8',
            backgroundColor: item.checked ? '#C4737E' : 'transparent',
          }}
        >
          {item.checked && (
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
              <path d="M2.5 7L5.5 10L11.5 4" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          )}
        </button>

        <div className={`flex-1 min-w-0 ${item.checked ? 'opacity-50' : ''}`}>
          <span className={`text-base sm:text-lg text-espresso ${item.checked ? 'line-through text-warm-grey' : ''}`}>
            {item.name}
          </span>
        </div>

        {amountText && (
          <span className={`text-sm flex-shrink-0 ${item.checked ? 'text-warm-grey/50 line-through' : 'text-warm-grey'}`}>
            {amountText}
          </span>
        )}
      </div>
    </li>
  )
}
