import { useEffect, useState } from 'react'
import type { Cart, CartTemplate, Section, Product, Drone } from '../types'
import { cacheImagesInCart, resolveImagesInCart, pruneImageCache } from '../utils/imageCache'

const CARTS_KEY     = 'carts'
const ACTIVE_KEY    = 'active-cart-id'

function loadCarts(): Cart[] {
  try {
    const raw = localStorage.getItem(CARTS_KEY)
    if (raw) return JSON.parse(raw) as Cart[]
  } catch {}
  return []
}

function loadActiveId(carts: Cart[]): string | null {
  const stored = localStorage.getItem(ACTIVE_KEY)
  if (stored && carts.find(c => c.id === stored)) return stored
  return carts[0]?.id ?? null
}

function saveCarts(carts: Cart[]): string | null {
  const json = JSON.stringify(carts)
  try {
    localStorage.setItem(CARTS_KEY, json)
    return null
  } catch {
    // Some browsers can't replace a large value in one step — free it first, then retry
    try {
      localStorage.removeItem(CARTS_KEY)
      localStorage.setItem(CARTS_KEY, json)
      return null
    } catch (e) {
      if (e instanceof DOMException && e.name === 'QuotaExceededError') {
        return 'Storage quota exceeded — images may be too large. Try removing unused images.'
      }
      return 'Failed to save carts.'
    }
  }
}

export function useCarts() {
  const [carts, setCarts] = useState<Cart[]>(() => loadCarts())
  const [activeId, setActiveId] = useState<string | null>(() => {
    const c = loadCarts()
    return loadActiveId(c)
  })

  // Migrate any inline base64 images to IndexedDB on first load
  useEffect(() => {
    const loaded = loadCarts()
    const needsMigration = loaded.some(cart =>
      cart.sections.some(s => s.items.some(item =>
        (item.image && !item.image.startsWith('img:')) ||
        ('parts' in item && item.parts.some(p => p.image && !p.image.startsWith('img:')))
      ))
    )
    if (!needsMigration) return
    Promise.all(loaded.map(cacheImagesInCart)).then(migrated => {
      pruneImageCache(migrated)
      const err = saveCarts(migrated)
      setStorageError(err)
      setCarts(migrated)
    })
  }, [])
  const [storageError, setStorageError] = useState<string | null>(null)

  const activeCart = carts.find(c => c.id === activeId) ?? null

  function mutateCarts(fn: (carts: Cart[]) => Cart[]) {
    setCarts(prev => {
      const next = fn(prev)
      pruneImageCache(next) // fire-and-forget async
      const err = saveCarts(next)
      setStorageError(err)
      return next
    })
  }

  function mutateActiveCart(fn: (cart: Cart) => Cart) {
    mutateCarts(carts => carts.map(c => c.id === activeId ? fn(c) : c))
  }

  // ── Cart management ────────────────────────────────────────────────────────

  async function createCart(name: string, template?: CartTemplate): Promise<string> {
    const id = crypto.randomUUID()
    const raw: Cart = {
      id,
      name,
      createdAt: new Date().toISOString().slice(0, 10),
      templateId: template?.id,
      sections: template ? structuredClone(template.sections) : [],
    }
    const cart = template ? await cacheImagesInCart(raw) : raw
    mutateCarts(prev => [...prev, cart])
    setActiveCart(id)
    return id
  }

  function deleteCart(id: string) {
    mutateCarts(prev => {
      const next = prev.filter(c => c.id !== id)
      if (activeId === id) {
        const newActive = next[0]?.id ?? null
        setActiveId(newActive)
        if (newActive) localStorage.setItem(ACTIVE_KEY, newActive)
        else localStorage.removeItem(ACTIVE_KEY)
      }
      return next
    })
  }

  function renameCart(id: string, name: string) {
    mutateCarts(carts => carts.map(c => c.id === id ? { ...c, name } : c))
  }

  function setActiveCart(id: string) {
    setActiveId(id)
    localStorage.setItem(ACTIVE_KEY, id)
  }

  async function importCart(json: string): Promise<boolean> {
    try {
      const cart = JSON.parse(json) as Cart
      if (!cart.id || !cart.name || !Array.isArray(cart.sections)) return false
      const imported = await cacheImagesInCart({ ...cart, id: crypto.randomUUID() })
      mutateCarts(prev => [...prev, imported])
      setActiveCart(imported.id)
      return true
    } catch {
      return false
    }
  }

  async function exportCart() {
    if (!activeCart) return
    const resolved = await resolveImagesInCart(activeCart)
    const blob = new Blob([JSON.stringify(resolved, null, 2)], { type: 'application/json' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `${activeCart.name.toLowerCase().replace(/\s+/g, '-')}.json`
    a.click()
    URL.revokeObjectURL(url)
  }

  // ── Section management ────────────────────────────────────────────────────

  function addSection(section: Omit<Section, 'items'>) {
    mutateActiveCart(cart => ({
      ...cart,
      sections: [...cart.sections, { ...section, items: [] }],
    }))
  }

  function removeSection(sectionId: string) {
    mutateActiveCart(cart => ({
      ...cart,
      sections: cart.sections.filter(s => s.id !== sectionId),
    }))
  }

  function renameSection(sectionId: string, label: string) {
    mutateActiveCart(cart => ({
      ...cart,
      sections: cart.sections.map(s => s.id === sectionId ? { ...s, label } : s),
    }))
  }

  function reorderSections(fromId: string, toId: string) {
    mutateActiveCart(cart => {
      const sections = [...cart.sections]
      const fromIdx = sections.findIndex(s => s.id === fromId)
      const toIdx   = sections.findIndex(s => s.id === toId)
      if (fromIdx === -1 || toIdx === -1 || fromIdx === toIdx) return cart
      const [moved] = sections.splice(fromIdx, 1)
      sections.splice(toIdx, 0, moved)
      return { ...cart, sections }
    })
  }

  // ── Item management ───────────────────────────────────────────────────────

  function addItem(sectionId: string, item: Product | Drone) {
    mutateActiveCart(cart => ({
      ...cart,
      sections: cart.sections.map(s =>
        s.id === sectionId ? { ...s, items: [...s.items, item] } : s
      ),
    }))
  }

  function updateItem(sectionId: string, item: Product | Drone) {
    mutateActiveCart(cart => ({
      ...cart,
      sections: cart.sections.map(s =>
        s.id === sectionId
          ? { ...s, items: s.items.map(i => i.id === item.id ? item : i) }
          : s
      ),
    }))
  }

  function removeItem(sectionId: string, itemId: string) {
    mutateActiveCart(cart => ({
      ...cart,
      sections: cart.sections.map(s =>
        s.id === sectionId
          ? { ...s, items: s.items.filter(i => i.id !== itemId) }
          : s
      ),
    }))
  }

  function copyItemToCart(item: Product | Drone, targetCartId: string, targetSectionId: string) {
    const copy = { ...structuredClone(item), id: crypto.randomUUID() }
    mutateCarts(carts => carts.map(c => {
      if (c.id !== targetCartId) return c
      const hasSection = c.sections.some(s => s.id === targetSectionId)
      if (!hasSection) return c
      return {
        ...c,
        sections: c.sections.map(s =>
          s.id === targetSectionId ? { ...s, items: [...s.items, copy] } : s
        ),
      }
    }))
  }

  return {
    carts,
    activeCart,
    activeId,
    storageError,
    setActiveCart,
    createCart,
    deleteCart,
    renameCart,
    importCart,
    exportCart,
    addSection,
    removeSection,
    renameSection,
    reorderSections,
    addItem,
    updateItem,
    removeItem,
    copyItemToCart,
  }
}
