import { db, id, now, visibleClause } from '../db.js';
import { customVariableSchema } from '../forms/schemas.js';
import { fullVariableCatalog } from '../data/variableCatalog.js';
import { decryptSecret, encryptSecret } from '../services/cryptoStore.js';
import { camelCustomVariable } from './mappers.js';

function normalizeVariable(body, existing = {}) {
  const parsed = customVariableSchema.parse({ ...existing, ...body });
  return {
    ...parsed,
    sensitive: Boolean(parsed.sensitive),
    groupId: parsed.visibility === 'group' ? parsed.groupId || null : null
  };
}

function visibleCustomVariableRows(userId) {
  return db.prepare(`
    SELECT v.*, g.name AS group_name
    FROM custom_variables v
    LEFT JOIN groups g ON g.id = v.group_id
    WHERE ${visibleClause('v')}
    ORDER BY v.category, v.name
  `).all(userId, userId);
}

export function listVariableCatalog(userId) {
  const catalog = fullVariableCatalog();
  return {
    ...catalog,
    custom: visibleCustomVariableRows(userId).map((row) => {
      const includeValue = !Boolean(row.sensitive);
      const value = includeValue ? decryptSecret(row) : undefined;
      return camelCustomVariable({ ...row, value }, includeValue);
    })
  };
}

export function listCustomVariables(userId) {
  return visibleCustomVariableRows(userId).map((row) => {
    const includeValue = !Boolean(row.sensitive);
    const value = includeValue ? decryptSecret(row) : undefined;
    return camelCustomVariable({ ...row, value }, includeValue);
  });
}

export function listExecutableCustomVariables(userId) {
  return visibleCustomVariableRows(userId).map((row) => ({
    id: row.id,
    name: row.name,
    value: decryptSecret(row),
    valueType: row.value_type || 'string',
    sensitive: Boolean(row.sensitive)
  }));
}

export function createCustomVariable(body, userId) {
  const payload = normalizeVariable(body);
  const encrypted = encryptSecret(payload.value);
  const variableId = id('var');
  db.prepare(`
    INSERT INTO custom_variables (
      id, name, description, category, value_type, secret_cipher, secret_iv, secret_tag,
      sensitive, visibility, owner_user_id, group_id, created_by, created_at, updated_at
    )
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `).run(
    variableId,
    payload.name,
    payload.description,
    payload.category,
    payload.valueType,
    encrypted.cipher,
    encrypted.iv,
    encrypted.tag,
    payload.sensitive ? 1 : 0,
    payload.visibility,
    userId,
    payload.groupId,
    userId,
    now(),
    now()
  );
  return loadCustomVariable(variableId, userId);
}

export function loadCustomVariable(variableId, userId) {
  const row = db.prepare(`
    SELECT v.*, g.name AS group_name
    FROM custom_variables v
    LEFT JOIN groups g ON g.id = v.group_id
    WHERE v.id = ? AND ${visibleClause('v')}
  `).get(variableId, userId, userId);
  if (!row) return null;
  const includeValue = !Boolean(row.sensitive);
  const value = includeValue ? decryptSecret(row) : undefined;
  return camelCustomVariable({ ...row, value }, includeValue);
}

export function updateCustomVariable(variableId, body, userId) {
  const existing = db.prepare(`SELECT * FROM custom_variables WHERE id = ? AND ${visibleClause()}`).get(variableId, userId, userId);
  if (!existing) return null;
  const payload = normalizeVariable(body, {
    name: existing.name,
    description: existing.description || '',
    category: existing.category || 'Custom',
    value: body.value ?? decryptSecret(existing),
    valueType: existing.value_type || 'string',
    sensitive: Boolean(existing.sensitive),
    visibility: existing.visibility,
    groupId: existing.group_id
  });
  const encrypted = body.value === undefined ? {
    cipher: existing.secret_cipher,
    iv: existing.secret_iv,
    tag: existing.secret_tag
  } : encryptSecret(payload.value);
  db.prepare(`
    UPDATE custom_variables
    SET name = ?, description = ?, category = ?, value_type = ?, secret_cipher = ?, secret_iv = ?,
        secret_tag = ?, sensitive = ?, visibility = ?, group_id = ?, updated_at = ?
    WHERE id = ?
  `).run(
    payload.name,
    payload.description,
    payload.category,
    payload.valueType,
    encrypted.cipher,
    encrypted.iv,
    encrypted.tag,
    payload.sensitive ? 1 : 0,
    payload.visibility,
    payload.groupId,
    now(),
    variableId
  );
  return loadCustomVariable(variableId, userId);
}

export function deleteCustomVariable(variableId, userId) {
  db.prepare(`DELETE FROM custom_variables WHERE id = ? AND ${visibleClause()}`).run(variableId, userId, userId);
}
