import { useEffect, useState } from 'react'
import type { Cart, Product, Drone } from '../types'

const DB_NAME    = 'fpvshop-images'
const STORE_NAME = 'images'
const DB_VERSION = 1

// In-memory mirror for synchronous first-render access
const memCache = new Map<string, string>()

// ── IndexedDB helpers ─────────────────────────────────────────────────────────

let dbPromise: Promise<IDBDatabase> | null = null

function getDB(): Promise<IDBDatabase> {
  if (!dbPromise) dbPromise = new Promise((resolve, reject) => {
    const req = indexedDB.open(DB_NAME, DB_VERSION)
    req.onupgradeneeded = () => req.result.createObjectStore(STORE_NAME)
    req.onsuccess     = () => resolve(req.result)
    req.onerror       = () => reject(req.error)
  })
  return dbPromise
}

function idbGet(db: IDBDatabase, id: string): Promise<string | undefined> {
  return new Promise((resolve, reject) => {
    const req = db.transaction(STORE_NAME, 'readonly').objectStore(STORE_NAME).get(id)
    req.onsuccess = () => resolve(req.result as string | undefined)
    req.onerror   = () => reject(req.error)
  })
}

function idbPut(db: IDBDatabase, id: string, value: string): Promise<void> {
  return new Promise((resolve, reject) => {
    const req = db.transaction(STORE_NAME, 'readwrite').objectStore(STORE_NAME).put(value, id)
    req.onsuccess = () => resolve()
    req.onerror   = () => reject(req.error)
  })
}

function idbGetAllKeys(db: IDBDatabase): Promise<string[]> {
  return new Promise((resolve, reject) => {
    const req = db.transaction(STORE_NAME, 'readonly').objectStore(STORE_NAME).getAllKeys()
    req.onsuccess = () => resolve(req.result as string[])
    req.onerror   = () => reject(req.error)
  })
}

function idbDelete(db: IDBDatabase, id: string): Promise<void> {
  return new Promise((resolve, reject) => {
    const req = db.transaction(STORE_NAME, 'readwrite').objectStore(STORE_NAME).delete(id)
    req.onsuccess = () => resolve()
    req.onerror   = () => reject(req.error)
  })
}

// ── Public API ────────────────────────────────────────────────────────────────

export async function storeImage(dataUri: string): Promise<string> {
  if (!dataUri || dataUri.startsWith('img:')) return dataUri
  // Dedup via in-memory cache
  for (const [id, value] of memCache) {
    if (value === dataUri) return `img:${id}`
  }
  const id = crypto.randomUUID().replace(/-/g, '')
  memCache.set(id, dataUri)
  const db = await getDB()
  await idbPut(db, id, dataUri)
  return `img:${id}`
}

export function resolveImageSync(keyOrUri: string | undefined): string | undefined {
  if (!keyOrUri) return undefined
  if (!keyOrUri.startsWith('img:')) return keyOrUri
  return memCache.get(keyOrUri.slice(4))
}

export async function resolveImage(keyOrUri: string | undefined): Promise<string | undefined> {
  if (!keyOrUri) return undefined
  if (!keyOrUri.startsWith('img:')) return keyOrUri
  const id = keyOrUri.slice(4)
  if (memCache.has(id)) return memCache.get(id)
  const db = await getDB()
  const value = await idbGet(db, id)
  if (value) memCache.set(id, value)
  return value
}

export function useResolvedImage(keyOrUri: string | undefined): string | undefined {
  const [resolved, setResolved] = useState(() => resolveImageSync(keyOrUri))
  useEffect(() => {
    resolveImage(keyOrUri).then(v => setResolved(v))
  }, [keyOrUri])
  return resolved
}

export async function pruneImageCache(carts: Cart[]): Promise<void> {
  const used = new Set<string>()
  for (const cart of carts) {
    for (const section of cart.sections) {
      for (const item of section.items) {
        if (item.image?.startsWith('img:')) used.add(item.image.slice(4))
        if ('parts' in item) {
          for (const part of item.parts) {
            if (part.image?.startsWith('img:')) used.add(part.image.slice(4))
          }
        }
      }
    }
  }
  const db = await getDB()
  const keys = await idbGetAllKeys(db)
  for (const id of keys) {
    if (!used.has(id)) { await idbDelete(db, id); memCache.delete(id) }
  }
}

export async function cacheItemImages(item: Product | Drone): Promise<Product | Drone> {
  const clone = structuredClone(item)
  if (clone.image && !clone.image.startsWith('img:')) clone.image = await storeImage(clone.image)
  if ('parts' in clone) {
    for (const part of clone.parts) {
      if (part.image && !part.image.startsWith('img:')) part.image = await storeImage(part.image)
    }
  }
  return clone
}

export async function cacheImagesInCart(cart: Cart): Promise<Cart> {
  const clone = structuredClone(cart)
  for (const section of clone.sections) {
    for (let i = 0; i < section.items.length; i++) {
      section.items[i] = await cacheItemImages(section.items[i])
    }
  }
  return clone
}

export async function resolveImagesInCart(cart: Cart): Promise<Cart> {
  const clone = structuredClone(cart)
  for (const section of clone.sections) {
    for (const item of section.items) {
      if (item.image) item.image = await resolveImage(item.image) ?? item.image
      if ('parts' in item) {
        for (const part of item.parts) {
          if (part.image) part.image = await resolveImage(part.image) ?? part.image
        }
      }
    }
  }
  return clone
}
