'use strict';

const { query, transaction, getDb } = require('./sqlite-client');

/**
 * Get all dimensions with counts.
 */
function getDimensions() {
  const sql = `
    WITH dimension_counts AS (
      SELECT nd.dimension, COUNT(*) AS count
      FROM node_dimensions nd
      GROUP BY nd.dimension
    )
    SELECT
      d.name AS dimension,
      d.description,
      d.icon,
      d.is_priority AS isPriority,
      COALESCE(dc.count, 0) AS count
    FROM dimensions d
    LEFT JOIN dimension_counts dc ON dc.dimension = d.name
    ORDER BY d.is_priority DESC, d.name ASC
  `;

  const rows = query(sql);

  return rows.map(row => ({
    dimension: row.dimension,
    description: row.description,
    icon: row.icon || null,
    isPriority: Boolean(row.isPriority),
    count: Number(row.count)
  }));
}

/**
 * Create or update a dimension.
 */
function createDimension(data) {
  const { name, description, isPriority = false } = data;
  const db = getDb();

  if (!name || !name.trim()) {
    throw new Error('Dimension name is required');
  }

  const trimmedName = name.trim();

  const stmt = db.prepare(`
    INSERT INTO dimensions(name, description, is_priority, updated_at)
    VALUES (?, ?, ?, CURRENT_TIMESTAMP)
    ON CONFLICT(name) DO UPDATE SET
      description = COALESCE(?, description),
      is_priority = COALESCE(?, is_priority),
      updated_at = CURRENT_TIMESTAMP
    RETURNING name, description, is_priority
  `);

  const rows = stmt.all(
    trimmedName,
    description ?? null,
    isPriority ? 1 : 0,
    description ?? null,
    isPriority ? 1 : 0
  );

  if (rows.length === 0) {
    throw new Error('Failed to create dimension');
  }

  return {
    dimension: rows[0].name,
    description: rows[0].description,
    isPriority: Boolean(rows[0].is_priority)
  };
}

/**
 * Update a dimension.
 */
function updateDimension(data) {
  const { name, currentName, newName, description, isPriority } = data;
  const db = getDb();

  // Handle rename
  if (currentName && newName && currentName !== newName) {
    // Check if new name already exists
    const existing = query('SELECT name FROM dimensions WHERE name = ?', [newName]);
    if (existing.length > 0) {
      throw new Error('A dimension with this name already exists');
    }

    transaction(() => {
      // Update dimensions table
      const dimStmt = db.prepare(`
        UPDATE dimensions
        SET name = ?, updated_at = CURRENT_TIMESTAMP
        WHERE name = ?
      `);
      const dimResult = dimStmt.run(newName, currentName);

      if (dimResult.changes === 0) {
        throw new Error('Dimension not found. Use rah_list_dimensions to see all dimensions.');
      }

      // Update node_dimensions
      const nodeDimStmt = db.prepare(`
        UPDATE node_dimensions
        SET dimension = ?
        WHERE dimension = ?
      `);
      nodeDimStmt.run(newName, currentName);
    });

    return {
      dimension: newName,
      previousName: currentName,
      renamed: true
    };
  }

  // Handle update (description/isPriority)
  const targetName = name || currentName;
  if (!targetName) {
    throw new Error('Dimension name is required');
  }

  const updates = [];
  const params = [];

  if (description !== undefined) {
    updates.push('description = ?');
    params.push(description);
  }

  if (isPriority !== undefined) {
    updates.push('is_priority = ?');
    params.push(isPriority ? 1 : 0);
  }

  if (updates.length === 0) {
    throw new Error('At least one update field must be provided (description, isPriority, or newName).');
  }

  updates.push('updated_at = CURRENT_TIMESTAMP');
  params.push(targetName);

  const stmt = db.prepare(`
    UPDATE dimensions
    SET ${updates.join(', ')}
    WHERE name = ?
  `);

  const result = stmt.run(...params);

  if (result.changes === 0) {
    throw new Error('Dimension not found. Use rah_list_dimensions to see all dimensions.');
  }

  return {
    dimension: targetName,
    description,
    isPriority
  };
}

/**
 * Delete a dimension.
 */
function deleteDimension(name) {
  const db = getDb();

  if (!name || !name.trim()) {
    throw new Error('Dimension name is required');
  }

  const removal = transaction(() => {
    const nodeDimStmt = db.prepare('DELETE FROM node_dimensions WHERE dimension = ?');
    const dimStmt = db.prepare('DELETE FROM dimensions WHERE name = ?');

    const removedLinks = nodeDimStmt.run(name).changes ?? 0;
    const removedRow = dimStmt.run(name).changes ?? 0;

    return { removedLinks, removedRow };
  });

  if (!removal.removedLinks && !removal.removedRow) {
    throw new Error('Dimension not found. Use rah_list_dimensions to see all dimensions.');
  }

  return {
    dimension: name,
    deleted: true,
    removedLinks: removal.removedLinks
  };
}

module.exports = {
  getDimensions,
  createDimension,
  updateDimension,
  deleteDimension
};
