import type { TraceFile } from '../../types/trace'

export interface TraceRecord {
  id: string
  name: string
  uploadedAt: Date
  fileSize: number
  eventCount: number
  duration: number
  traceData: TraceFile
}

const DB_NAME = 'PerfVizTraces'
const DB_VERSION = 1
const STORE_NAME = 'traces'

class TraceDatabase {
  private db: IDBDatabase | null = null

  async init(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(DB_NAME, DB_VERSION)

      request.onerror = () => reject(request.error)
      request.onsuccess = () => {
        this.db = request.result
        resolve()
      }

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result
        
        // Create traces object store
        const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' })
        store.createIndex('name', 'name', { unique: false })
        store.createIndex('uploadedAt', 'uploadedAt', { unique: false })
        store.createIndex('fileSize', 'fileSize', { unique: false })
      }
    })
  }

  async addTrace(traceData: TraceFile, filename: string, fileSize: number): Promise<string> {
    if (!this.db) throw new Error('Database not initialized')

    const id = `trace_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
    
    // Calculate basic stats
    const eventCount = traceData.traceEvents.length
    let minTs = Infinity
    let maxTs = -Infinity
    
    for (const event of traceData.traceEvents) {
      if (event.ts > 0) {
        minTs = Math.min(minTs, event.ts)
        maxTs = Math.max(maxTs, event.ts)
      }
    }
    
    const duration = maxTs - minTs

    const record: TraceRecord = {
      id,
      name: filename,
      uploadedAt: new Date(),
      fileSize,
      eventCount,
      duration,
      traceData
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAME], 'readwrite')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.add(record)

      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve(id)
    })
  }

  async getAllTraces(): Promise<TraceRecord[]> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAME], 'readonly')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.getAll()

      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve(request.result)
    })
  }

  async getTrace(id: string): Promise<TraceRecord | null> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAME], 'readonly')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.get(id)

      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve(request.result || null)
    })
  }

  async deleteTrace(id: string): Promise<void> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAME], 'readwrite')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.delete(id)

      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve()
    })
  }

  async updateTraceName(id: string, newName: string): Promise<void> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAME], 'readwrite')
      const store = transaction.objectStore(STORE_NAME)
      const getRequest = store.get(id)

      getRequest.onsuccess = () => {
        const record = getRequest.result
        if (record) {
          record.name = newName
          const updateRequest = store.put(record)
          updateRequest.onsuccess = () => resolve()
          updateRequest.onerror = () => reject(updateRequest.error)
        } else {
          reject(new Error('Trace not found'))
        }
      }

      getRequest.onerror = () => reject(getRequest.error)
    })
  }

  async clearAllTraces(): Promise<void> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAME], 'readwrite')
      const store = transaction.objectStore(STORE_NAME)
      const request = store.clear()

      request.onerror = () => reject(request.error)
      request.onsuccess = () => resolve()
    })
  }
}

// Singleton instance
export const traceDatabase = new TraceDatabase()