import { useRef, useState } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { Plus, Search, Trash2, Package, AlertTriangle } from 'lucide-react'
import { mealPlannerApi } from '../api'
import { PANTRY_AISLES, type HomePantryItem, type Ingredient } from '../types'
import { Button } from '../components/ui/Button'
import { Card, CardBody } from '../components/ui/Card'
import { Input } from '../components/ui/Input'
import { Select } from '../components/ui/Select'
import { Skeleton, SkeletonText } from '../components/ui/Skeleton'
import { EmptyState } from '../components/ui/EmptyState'
import { showToast, showApiError } from '../lib/toast'
import { useFocusSearchOnShortcut } from '../hooks/useFocusSearch'

const AISLE_OPTIONS = [
  { value: '', label: 'Select aisle…' },
  ...PANTRY_AISLES.map(a => ({ value: a, label: a })),
]

export default function Pantry() {
  const queryClient = useQueryClient()
  const [showAddForm, setShowAddForm] = useState(false)
  const [removeId, setRemoveId] = useState<string | null>(null)
  const [searchQuery, setSearchQuery] = useState('')
  const searchInputRef = useRef<HTMLInputElement>(null)
  useFocusSearchOnShortcut(searchInputRef)

  /* ingredient name typed by user */
  const [ingredientName, setIngredientName] = useState('')
  const [quantity, setQuantity] = useState('')
  const [unit, setUnit] = useState('')
  const [aisle, setAisle] = useState('')

  const { data: pantryItems, isLoading } = useQuery<HomePantryItem[]>({
    queryKey: ['pantry'],
    queryFn: () => mealPlannerApi.pantry.list().then(r => r.data),
  })

  const { data: ingredients } = useQuery<Ingredient[]>({
    queryKey: ['ingredients'],
    queryFn: () => mealPlannerApi.recipes.listIngredients().then(r => r.data),
  })

  function _ingredientMatchesName(ing: Ingredient, search: string): boolean {
    const s = search.toLowerCase()
    return ing.name.toLowerCase() === s || (ing.aliases ?? []).some(a => a.toLowerCase() === s)
  }

  /* fuzzy match existing ingredient */
  const matchedIngredient = ingredientName.trim().length > 0
    ? ingredients?.find(
        ing => _ingredientMatchesName(ing, ingredientName.trim())
      )
    : undefined

  const addMutation = useMutation({
    mutationFn: (data: { ingredient_id: string; quantity?: number; unit?: string }) =>
      mealPlannerApi.pantry.add(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['pantry'] })
      setShowAddForm(false)
      setIngredientName('')
      setQuantity('')
      setUnit('')
      setAisle('')
      showToast.success('Item added to pantry')
    },
  })

  const removeMutation = useMutation({
    mutationFn: (id: string) => mealPlannerApi.pantry.remove(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['pantry'] })
      showToast.success('Item removed')
      setRemoveId(null)
    },
  })

  async function handleRemove(item: HomePantryItem) {
    if (!item.ingredient_id) {
      showToast.error('Cannot remove: missing ingredient link')
      return
    }
    setRemoveId(item.id)
    try {
      await mealPlannerApi.pantry.remove(item.id)
      queryClient.invalidateQueries({ queryKey: ['pantry'] })
      showToast.undo(
        'Item removed',
        async () => {
          try {
            await mealPlannerApi.pantry.add({
              ingredient_id: item.ingredient_id!,
              quantity: item.quantity,
              unit: item.unit,
            })
            queryClient.invalidateQueries({ queryKey: ['pantry'] })
            showToast.success('Item restored')
          } catch (err) {
            showApiError(err, 'Failed to restore item')
          }
        }
      )
    } catch {
      // Error toast fires from the global MutationCache handler.
    } finally {
      setRemoveId(null)
    }
  }

  async function handleAdd() {
    const name = ingredientName.trim()
    if (!name) {
      showToast.error('Please enter an ingredient name')
      return
    }

    let ingredientId = matchedIngredient?.id

    if (!ingredientId) {
      try {
        const res = await mealPlannerApi.recipes.createIngredient({
          name,
          aisle: aisle.trim() || undefined,
          unit: unit.trim() || undefined,
        })
        const created = res.data as any
        ingredientId = created?.id
        // refresh ingredient list so next add sees it
        await queryClient.invalidateQueries({ queryKey: ['ingredients'] })
      } catch {
        // Error toast fires from the global MutationCache handler.
        return
      }
    }

    if (!ingredientId) {
      showToast.error('Could not resolve ingredient')
      return
    }

    addMutation.mutate({
      ingredient_id: ingredientId,
      quantity: quantity ? parseFloat(quantity) : undefined,
      unit: unit.trim() || undefined,
    })
  }

  const filteredItems = pantryItems?.filter(item =>
    item.ingredient?.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
    (item.ingredient?.aisle || '').toLowerCase().includes(searchQuery.toLowerCase())
  )

  if (isLoading) {
    return (
      <div className="space-y-6 animate-fade-in">
        <div className="flex justify-between items-center">
          <Skeleton className="h-8 w-32" />
          <Skeleton className="h-9 w-28" />
        </div>
        <Card>
          <CardBody>
            <SkeletonText lines={3} />
          </CardBody>
        </Card>
        <Card>
          <CardBody>
            <div className="space-y-3">
              {Array.from({ length: 5 }).map((_, i) => (
                <div key={i} className="flex justify-between">
                  <Skeleton className="h-5 w-48" />
                  <Skeleton className="h-5 w-20" />
                </div>
              ))}
            </div>
          </CardBody>
        </Card>
      </div>
    )
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-xl bg-warning-50 flex items-center justify-center">
            <Package className="w-5 h-5 text-warning-600" />
          </div>
          <div>
            <h1 className="text-2xl font-bold text-surface-900">Home Pantry</h1>
            <p className="text-sm text-surface-500">
              {pantryItems?.length || 0} items
            </p>
          </div>
        </div>
        <Button
          icon={<Plus className="w-4 h-4" />}
          onClick={() => setShowAddForm(!showAddForm)}
          variant={showAddForm ? 'secondary' : 'primary'}
        >
          {showAddForm ? 'Cancel' : 'Add Item'}
        </Button>
      </div>

      {/* Add Form */}
      {showAddForm && (
        <Card className="animate-slide-down">
          <CardBody>
            <h3 className="text-lg font-semibold text-surface-900 mb-4">Add Pantry Item</h3>
            <div className="grid grid-cols-1 md:grid-cols-5 gap-4">
              <div className="md:col-span-2">
                <Input
                  label="Ingredient name *"
                  value={ingredientName}
                  onChange={(e) => setIngredientName(e.target.value)}
                  placeholder="e.g., Avocado"
                  required
                />
                {matchedIngredient && (
                  <p className="mt-1 text-xs text-success-600">Matched existing ingredient ✓</p>
                )}
              </div>
              <Input
                label="Quantity"
                type="number"
                value={quantity}
                onChange={(e) => setQuantity(e.target.value)}
                placeholder="e.g., 5"
              />
              <Select
                label="Unit"
                value={unit}
                onChange={(e) => setUnit(e.target.value)}
                options={[
                  { value: '', label: 'Select unit…' },
                  { value: 'each', label: 'each' },
                  { value: 'g', label: 'g' },
                  { value: 'kg', label: 'kg' },
                  { value: 'oz', label: 'oz' },
                  { value: 'lb', label: 'lb' },
                  { value: 'ml', label: 'ml' },
                  { value: 'l', label: 'l' },
                  { value: 'cup', label: 'cup' },
                  { value: 'tbsp', label: 'tbsp' },
                  { value: 'tsp', label: 'tsp' },
                  { value: 'can', label: 'can' },
                  { value: 'bunch', label: 'bunch' },
                  { value: 'clove', label: 'clove' },
                ]}
              />
              <Select
                label="Aisle"
                value={aisle}
                onChange={(e) => setAisle(e.target.value)}
                options={AISLE_OPTIONS}
              />
              <div className="flex items-end">
                <Button
                  onClick={handleAdd}
                  loading={addMutation.isPending}
                  disabled={!ingredientName.trim() || addMutation.isPending}
                  className="w-full"
                >
                  Add
                </Button>
              </div>
            </div>
          </CardBody>
        </Card>
      )}

      {/* Search */}
      {pantryItems && pantryItems.length > 0 && (
        <div className="relative">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-surface-400" />
          <Input
            ref={searchInputRef}
            value={searchQuery}
            onChange={(e) => setSearchQuery(e.target.value)}
            placeholder="Search pantry items..."
            className="pl-10"
          />
        </div>
      )}

      {/* Items List */}
      {filteredItems && filteredItems.length > 0 ? (
        <Card className="overflow-hidden">
          <div className="relative">
            <div
              className="overflow-x-auto"
              role="region"
              aria-label="Pantry items, scroll horizontally to see all columns"
            >
              <table className="w-full">
                <thead>
                  <tr className="border-b border-surface-200 bg-surface-50">
                    <th className="px-6 py-3 text-left text-xs font-semibold text-surface-500 uppercase tracking-wider">Item</th>
                    <th className="px-6 py-3 text-left text-xs font-semibold text-surface-500 uppercase tracking-wider">Aisle</th>
                    <th className="px-6 py-3 text-left text-xs font-semibold text-surface-500 uppercase tracking-wider">Quantity</th>
                    <th className="px-6 py-3 text-left text-xs font-semibold text-surface-500 uppercase tracking-wider">Expires</th>
                    <th className="px-6 py-3 text-right text-xs font-semibold text-surface-500 uppercase tracking-wider">Actions</th>
                  </tr>
                </thead>
              <tbody className="divide-y divide-surface-200">
                {filteredItems.map((item) => {
                  const isExpiringSoon = item.expires_at &&
                    new Date(item.expires_at).getTime() - Date.now() < 7 * 24 * 60 * 60 * 1000

                  return (
                    <tr key={item.id} className="hover:bg-surface-50 transition-colors">
                      <td className="px-6 py-4">
                        <div className="flex items-center gap-3">
                          <div className="w-8 h-8 rounded-lg bg-primary-50 flex items-center justify-center flex-shrink-0">
                            <Package className="w-4 h-4 text-primary-600" />
                          </div>
                          <span className="font-medium text-sm text-surface-900">
                            {item.ingredient?.name || 'Unknown'}
                          </span>
                        </div>
                      </td>
                      <td className="px-6 py-4 text-sm text-surface-500">
                        {item.ingredient?.aisle || <span className="text-surface-400">—</span>}
                      </td>
                      <td className="px-6 py-4">
                        <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-surface-100 text-surface-700">
                          {item.quantity} {item.unit || ''}
                        </span>
                      </td>
                      <td className="px-6 py-4">
                        {item.expires_at ? (
                          <div className="flex items-center gap-1.5">
                            {isExpiringSoon && <AlertTriangle className="w-4 h-4 text-warning-500" />}
                            <span className={`text-sm ${isExpiringSoon ? 'text-warning-600 font-medium' : 'text-surface-500'}`}>
                              {new Date(item.expires_at).toLocaleDateString()}
                            </span>
                          </div>
                        ) : (
                          <span className="text-sm text-surface-400">—</span>
                        )}
                      </td>
                      <td className="px-6 py-4 text-right">
                        <Button
                          variant="ghost"
                          size="sm"
                          icon={<Trash2 className="w-4 h-4" />}
                          onClick={() => handleRemove(item)}
                          loading={removeMutation.isPending && removeId === item.id}
                          disabled={removeMutation.isPending}
                        >
                          Remove
                        </Button>
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
            </div>
            <div
              className="pointer-events-none absolute inset-y-0 right-0 w-8 bg-gradient-to-l from-white to-transparent md:hidden"
              aria-hidden="true"
            />
          </div>
        </Card>
      ) : (
        <EmptyState
          icon={Package}
          title={searchQuery ? 'No matches found' : 'Your pantry is empty'}
          description={
            searchQuery
              ? "Try adjusting your search."
              : "Add ingredients you already have at home to avoid buying duplicates."
          }
          action={
            !searchQuery
              ? { label: 'Add your first item', onClick: () => setShowAddForm(true) }
              : undefined
          }
        />
      )}
    </div>
  )
}
