import { db } from '../database.js'
import { escapeLike } from '../../utils/escapeLike.js'

export const collectionRepository = {
  async create(collection) {
    const id = crypto.randomUUID()
    await db.run('INSERT INTO collection (id, label, created_by) VALUES (?, ?, ?)', [
      id,
      collection.label,
      collection.created_by,
    ])
    return id
  },

  async getById(id) {
    const row = await db.selectOne('SELECT * FROM collection WHERE id = ?', [id])
    if (!row) return null
    row.sessions = await this.getSessions(id)
    return row
  },

  async getAll() {
    return db.selectAll(
      `SELECT c.*, COUNT(cs.session_id) AS sessionCount
       FROM collection c
       LEFT JOIN collection_session cs ON cs.collection_id = c.id
       GROUP BY c.id
       ORDER BY c.label`,
    )
  },

  async getAllWithSessions() {
    const collections = await db.selectAll('SELECT * FROM collection ORDER BY label')
    for (const c of collections) {
      c.sessions = await this.getSessions(c.id)
      const row = await db.selectOne(
        'SELECT COUNT(*) AS sessionCount FROM collection_session WHERE collection_id = ?',
        [c.id],
      )
      c.sessionCount = row ? row.sessionCount : 0
    }
    return collections
  },

  async searchWithSessions(query) {
    const collections = await this.search(query)
    for (const c of collections) {
      c.sessions = await this.getSessions(c.id)
      const row = await db.selectOne(
        'SELECT COUNT(*) AS sessionCount FROM collection_session WHERE collection_id = ?',
        [c.id],
      )
      c.sessionCount = row ? row.sessionCount : 0
    }
    return collections
  },

  async update(id, data) {
    return db.run('UPDATE collection SET label = ? WHERE id = ?', [data.label, id])
  },

  async delete(id) {
    return db.run('DELETE FROM collection WHERE id = ?', [id])
  },

  async createWithId(id, collection) {
    await db.run('INSERT INTO collection (id, label, created_by) VALUES (?, ?, ?)', [
      id,
      collection.label,
      collection.created_by,
    ])
    return id
  },

  async replaceAll(id, collection) {
    await db.run(
      `UPDATE collection SET label = ?, created_by = ?
       WHERE id = ?`,
      [collection.label, collection.created_by, id],
    )
  },

  async search(query) {
    return db.selectAll("SELECT * FROM collection WHERE label LIKE ? ESCAPE '\\' ORDER BY label", [
      `%${escapeLike(query)}%`,
    ])
  },

  async countCollectionsUsingSession(sessionId) {
    const row = await db.selectOne(
      'SELECT COUNT(DISTINCT collection_id) AS count FROM collection_session WHERE session_id = ?',
      [sessionId],
    )
    return row ? row.count : 0
  },

  async getSessions(collectionId) {
    return db.selectAll(
      `SELECT cs.position, cs.session_id, s.title
       FROM collection_session cs
       JOIN session s ON s.id = cs.session_id
       WHERE cs.collection_id = ?
       ORDER BY cs.position`,
      [collectionId],
    )
  },

  async getRawSessions(collectionId) {
    return db.selectAll(
      `SELECT cs.position, cs.session_id
       FROM collection_session cs
       WHERE cs.collection_id = ?
       ORDER BY cs.position`,
      [collectionId],
    )
  },

  async setSessions(collectionId, sessionIds) {
    const statements = [
      { sql: 'DELETE FROM collection_session WHERE collection_id = ?', params: [collectionId] },
      ...sessionIds.map((sessionId, i) => ({
        sql: 'INSERT INTO collection_session (collection_id, session_id, position) VALUES (?, ?, ?)',
        params: [collectionId, sessionId, i],
      })),
    ]
    await db.batch(statements)
  },
}
