import type { GenerateResponse } from './types'

const DB_NAME = 'cruciverb-offline'
const DB_VERSION = 1

function openDB(): Promise<IDBDatabase> {
  return new Promise((resolve, reject) => {
    const req = indexedDB.open(DB_NAME, DB_VERSION)
    req.onupgradeneeded = () => {
      const db = req.result
      if (!db.objectStoreNames.contains('puzzles')) {
        db.createObjectStore('puzzles', { keyPath: 'id' })
      }
      if (!db.objectStoreNames.contains('progress')) {
        db.createObjectStore('progress', { keyPath: 'puzzleId' })
      }
      if (!db.objectStoreNames.contains('pending')) {
        db.createObjectStore('pending', { keyPath: 'id', autoIncrement: true })
      }
    }
    req.onsuccess = () => resolve(req.result)
    req.onerror = () => reject(req.error)
  })
}

export async function cachePuzzle(id: string, data: GenerateResponse): Promise<void> {
  const db = await openDB()
  const tx = db.transaction('puzzles', 'readwrite')
  tx.objectStore('puzzles').put({ id, data, cached_at: Date.now() })
  return new Promise((resolve, reject) => { tx.oncomplete = () => resolve(); tx.onerror = () => reject(tx.error) })
}

export async function getCachedPuzzle(id: string): Promise<GenerateResponse | null> {
  const db = await openDB()
  return new Promise((resolve, reject) => {
    const tx = db.transaction('puzzles', 'readonly')
    const req = tx.objectStore('puzzles').get(id)
    req.onsuccess = () => resolve(req.result?.data || null)
    req.onerror = () => reject(req.error)
  })
}

export async function saveProgress(puzzleId: string, entries: string[][]): Promise<void> {
  const db = await openDB()
  const tx = db.transaction('progress', 'readwrite')
  tx.objectStore('progress').put({ puzzleId, entries, saved_at: Date.now() })
  return new Promise((resolve, reject) => { tx.oncomplete = () => resolve(); tx.onerror = () => reject(tx.error) })
}

export async function getProgress(puzzleId: string): Promise<string[][] | null> {
  const db = await openDB()
  return new Promise((resolve, reject) => {
    const tx = db.transaction('progress', 'readonly')
    const req = tx.objectStore('progress').get(puzzleId)
    req.onsuccess = () => resolve(req.result?.entries || null)
    req.onerror = () => reject(req.error)
  })
}

export function isOnline(): boolean {
  return navigator.onLine
}

export function onOnlineChange(callback: (online: boolean) => void): () => void {
  const onOnline = () => callback(true)
  const onOffline = () => callback(false)
  window.addEventListener('online', onOnline)
  window.addEventListener('offline', onOffline)
  return () => {
    window.removeEventListener('online', onOnline)
    window.removeEventListener('offline', onOffline)
  }
}
