/**
 * SummaryRepository - CRUD + get, insert for summaries table (§17)
 *
 * Implements Repository<SummaryRecord, SummaryInsert, SummaryUpdate> per contracts §6.
 *
 * @module packages/runtime/src/storage/repositories/SummaryRepository
 */

import type {
  Repository,
  TransactionHandle,
  SessionID,
  SummaryID,
  MessageID,
  ISOTimeString,
} from '@aircoding/contracts'

import { DatabaseHandle } from '../MigrationRunner.js'
import { assertEnumValues } from '../assertEnum.js'

// =============================================================================
// Types - per db-schema §17
// =============================================================================

export type SummaryType = 'compaction' | 'checkpoint' | 'review' | 'other'

export interface SummaryRecord {
  id: SummaryID
  session_id: SessionID
  type: SummaryType
  range_start_message_id?: MessageID
  range_end_message_id?: MessageID
  content_json: string
  created_at: ISOTimeString
  metadata_json?: string
}

export type SummaryInsert = Omit<SummaryRecord, 'id'> & {
  id?: SummaryID
}

export type SummaryUpdate = Partial<Omit<SummaryRecord, 'id' | 'session_id' | 'created_at'>>

// =============================================================================
// SummaryRepository
// =============================================================================

export class SummaryRepository implements Repository<SummaryRecord, SummaryInsert, SummaryUpdate> {
  private db: DatabaseHandle

  constructor(db: DatabaseHandle) {
    this.db = db
  }

  /**
   * Get a summary by ID.
   */
  async get(id: SummaryID, tx?: TransactionHandle): Promise<SummaryRecord | undefined> {
    const stmt = (tx?.db ?? this.db).prepare('SELECT * FROM summaries WHERE id = ?')
    const row = stmt.get(id) as SummaryRecord | undefined
    return row
  }

  /**
   * Insert a new summary.
   */
  async insert(record: SummaryInsert, tx?: TransactionHandle): Promise<void> {
    // Validate enum columns
    assertEnumValues('summaries', {
      type: record.type,
    })

    const stmt = (tx?.db ?? this.db).prepare(`
      INSERT INTO summaries (
        id, session_id, type,
        range_start_message_id, range_end_message_id,
        content_json, created_at, metadata_json
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `)

    stmt.run(
      record.id,
      record.session_id,
      record.type,
      record.range_start_message_id ?? null,
      record.range_end_message_id ?? null,
      record.content_json,
      record.created_at,
      record.metadata_json ?? null,
    )
  }

  /**
   * Update an existing summary.
   */
  async update(id: SummaryID, patch: SummaryUpdate, tx?: TransactionHandle): Promise<void> {
    // Validate enum columns if present
    if (patch.type !== undefined) {
      assertEnumValues('summaries', { type: patch.type })
    }

    const fields: string[] = []
    const values: unknown[] = []

    if (patch.type !== undefined) {
      fields.push('type = ?')
      values.push(patch.type)
    }
    if (patch.range_start_message_id !== undefined) {
      fields.push('range_start_message_id = ?')
      values.push(patch.range_start_message_id)
    }
    if (patch.range_end_message_id !== undefined) {
      fields.push('range_end_message_id = ?')
      values.push(patch.range_end_message_id)
    }
    if (patch.content_json !== undefined) {
      fields.push('content_json = ?')
      values.push(patch.content_json)
    }
    if (patch.metadata_json !== undefined) {
      fields.push('metadata_json = ?')
      values.push(patch.metadata_json)
    }

    if (fields.length === 0) {
      return // Nothing to update
    }

    values.push(id)
    const stmt = (tx?.db ?? this.db).prepare(`UPDATE summaries SET ${fields.join(', ')} WHERE id = ?`)
    stmt.run(...values)
  }

  // =============================================================================
  // Extra methods
  // =============================================================================

  /**
   * Get the most recent summary of a specific type for a session.
   */
  async get_latest(session_id: SessionID, type: SummaryType): Promise<SummaryRecord | undefined> {
    const stmt = this.db.prepare(
      'SELECT * FROM summaries WHERE session_id = ? AND type = ? ORDER BY created_at DESC LIMIT 1',
    )
    const row = stmt.get(session_id, type) as SummaryRecord | undefined
    return row
  }

  /**
   * List all summaries for a session.
   */
  async list_by_session(session_id: SessionID): Promise<SummaryRecord[]> {
    const stmt = this.db.prepare(
      'SELECT * FROM summaries WHERE session_id = ? ORDER BY created_at DESC',
    )
    return stmt.all(session_id) as SummaryRecord[]
  }
}