import type { SupabaseClient } from '../../../supabase'
import { Session } from './session'
import type { CreateSessionParams, ListSessionsFilters } from '../types'

export class SessionManager {
  constructor(private db: SupabaseClient) {}

  async create(params: CreateSessionParams): Promise<Session> {
    const { resourceId, organizationId, userId, metadata, contextWindowSize } = params

    const { data, error } = await this.db
      .from('sessions')
      .insert({
        resource_id: resourceId,
        organization_id: organizationId,
        user_id: userId ?? null,
        memory_snapshot: { sessionMemory: {}, history: [] },
        metadata: (metadata as Record<string, never> | null) ?? null,
        session_total_turns: 0,
        ...(contextWindowSize !== undefined && { context_window_size: contextWindowSize })
      })
      .select()
      .single()

    if (error) {
      throw new Error(`Failed to create session: ${error.message}`)
    }

    return new Session(this.db, data)
  }

  async get(sessionId: string, organizationId: string): Promise<Session | null> {
    const { data, error } = await this.db
      .from('sessions')
      .select()
      .eq('session_id', sessionId)
      .eq('organization_id', organizationId)
      .is('deleted_at', null)
      .single()

    if (error) {
      if (error.code === 'PGRST116') {
        return null // Not found
      }
      throw new Error(`Failed to get session: ${error.message}`)
    }

    return new Session(this.db, data)
  }

  async list(filters: ListSessionsFilters): Promise<Session[]> {
    const { organizationId, userId, resourceId, limit = 50 } = filters

    let query = this.db
      .from('sessions')
      .select()
      .eq('organization_id', organizationId)
      .is('deleted_at', null)
      .order('created_at', { ascending: false })
      .limit(limit)

    if (userId) {
      query = query.eq('user_id', userId)
    }

    if (resourceId) {
      query = query.eq('resource_id', resourceId)
    }

    const { data, error } = await query

    if (error) {
      throw new Error(`Failed to list sessions: ${error.message}`)
    }

    return data.map((row) => new Session(this.db, row))
  }

  async delete(sessionId: string, organizationId: string): Promise<void> {
    const { error } = await this.db
      .from('sessions')
      .update({ deleted_at: new Date().toISOString() })
      .eq('session_id', sessionId)
      .eq('organization_id', organizationId)

    if (error) {
      throw new Error(`Failed to delete session: ${error.message}`)
    }
  }
}
