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

export const sessionRepository = {
  async create(session) {
    const id = crypto.randomUUID()
    await db.run(
      `INSERT INTO session (id, title, description, created_by)
       VALUES (?, ?, ?, ?)`,
      [id, session.title, session.description || '', session.created_by],
    )
    return id
  },

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

  async getAll() {
    return db.selectAll('SELECT * FROM session ORDER BY title')
  },

  async getAllWithItems() {
    const sessions = await this.getAll()
    for (const session of sessions) {
      session.items = await this.getItems(session.id)
    }
    return sessions
  },

  async searchWithItems(query) {
    const sessions = await this.search(query)
    for (const session of sessions) {
      session.items = await this.getItems(session.id)
    }
    return sessions
  },

  async update(id, data) {
    return db.run('UPDATE session SET title = ?, description = ? WHERE id = ?', [
      data.title,
      data.description || '',
      id,
    ])
  },

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

  async createWithId(id, session) {
    await db.run(
      `INSERT INTO session (id, title, description, created_by)
       VALUES (?, ?, ?, ?)`,
      [id, session.title, session.description || '', session.created_by],
    )
    return id
  },

  async replaceAll(id, session) {
    await db.run(
      `UPDATE session SET title = ?, description = ?, created_by = ?
       WHERE id = ?`,
      [session.title, session.description || '', session.created_by, id],
    )
  },

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

  async countSessionsUsingItem(itemId, itemType) {
    const row = await db.selectOne(
      'SELECT COUNT(DISTINCT session_id) AS count FROM session_item WHERE item_id = ? AND item_type = ?',
      [itemId, itemType],
    )
    return row ? row.count : 0
  },

  async getItems(sessionId) {
    const exerciseRows = await db.selectAll(
      `SELECT si.position, si.item_id, si.item_type, si.repetitions, si.weight, e.title
       FROM session_item si
       JOIN exercise e ON e.id = si.item_id
       WHERE si.session_id = ? AND si.item_type = 'exercise'
       ORDER BY si.position`,
      [sessionId],
    )
    const comboRows = await db.selectAll(
      `SELECT si.position, si.item_id, si.item_type, si.repetitions, si.weight, c.title, c.type AS combo_type
       FROM session_item si
       JOIN combo c ON c.id = si.item_id
       WHERE si.session_id = ? AND si.item_type = 'combo'
       ORDER BY si.position`,
      [sessionId],
    )
    return [...exerciseRows, ...comboRows].sort((a, b) => a.position - b.position)
  },

  async getRawItems(sessionId) {
    return db.selectAll(
      `SELECT si.position, si.item_id, si.item_type, si.repetitions, si.weight
       FROM session_item si
       WHERE si.session_id = ?
       ORDER BY si.position`,
      [sessionId],
    )
  },

  async setItems(sessionId, items) {
    const statements = [
      { sql: 'DELETE FROM session_item WHERE session_id = ?', params: [sessionId] },
      ...items.map((item, i) => ({
        sql: 'INSERT INTO session_item (session_id, item_id, item_type, position, repetitions, weight) VALUES (?, ?, ?, ?, ?, ?)',
        params: [
          sessionId,
          item.item_id,
          item.item_type,
          i,
          item.repetitions || 1,
          item.weight || 0.0,
        ],
      })),
    ]
    await db.batch(statements)
  },
}
