import { pool, query } from '../db/connection.js';
import { ulid } from 'ulid';

export type ShoppingScope = 'personal' | 'household';

export async function listItems(userId?: string, scope: ShoppingScope = 'personal') {
  let sql: string;
  let params: any[];

  if (!userId) {
    sql = `
      SELECT si.*, r.title as recipe_title
      FROM shopping_items si
      LEFT JOIN recipes r ON si.recipe_id = r.id
      WHERE si.user_id IS NULL AND si.household_id IS NULL
      ORDER BY si.checked, si.created_at DESC
    `;
    params = [];
  } else if (scope === 'household') {
    sql = `
      SELECT si.*, r.title as recipe_title
      FROM shopping_items si
      LEFT JOIN recipes r ON si.recipe_id = r.id
      LEFT JOIN household_members hm ON si.household_id = hm.household_id
      WHERE hm.user_id = $1 AND si.household_id IS NOT NULL
      ORDER BY si.checked, si.created_at DESC
    `;
    params = [userId];
  } else {
    sql = `
      SELECT si.*, r.title as recipe_title
      FROM shopping_items si
      LEFT JOIN recipes r ON si.recipe_id = r.id
      WHERE si.user_id = $1 AND si.household_id IS NULL
      ORDER BY si.checked, si.created_at DESC
    `;
    params = [userId];
  }

  const { rows: items } = await query(sql, params);

  const grouped: Record<string, any> = {};
  for (const item of items) {
    const key = item.recipe_id || '_custom';
    if (!grouped[key]) {
      grouped[key] = { recipe_id: item.recipe_id, recipe_title: item.recipe_title || 'Eigene Einträge', items: [] };
    }
    grouped[key].items.push(item);
  }
  return Object.values(grouped);
}

export async function addFromRecipe(recipeId: string, userId?: string, scope: ShoppingScope = 'personal') {
  const { rows: recipeRows } = await query('SELECT id FROM recipes WHERE id = $1', [recipeId]);
  if (recipeRows.length === 0) return null;

  const { rows: ingredients } = await query('SELECT * FROM ingredients WHERE recipe_id = $1', [recipeId]);

  let householdId = null;
  if (userId && scope === 'household') {
    const { rows } = await query('SELECT household_id FROM household_members WHERE user_id = $1', [userId]);
    if (rows.length === 0) throw new Error('USER_NOT_IN_HOUSEHOLD');
    householdId = rows[0].household_id;
  }

  const added: any[] = [];
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    for (const ing of ingredients) {
      const id = ulid();
      await client.query(
        'INSERT INTO shopping_items (id, name, amount, unit, recipe_id, user_id, household_id) VALUES ($1, $2, $3, $4, $5, $6, $7)',
        [id, ing.name, ing.amount, ing.unit, recipeId, userId || null, householdId]
      );
      added.push({ id, name: ing.name, amount: ing.amount, unit: ing.unit, recipe_id: recipeId, user_id: userId || null, household_id: householdId, checked: false });
    }
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
  return added;
}

export async function addItem(name: string, amount?: number, unit?: string, userId?: string, scope: ShoppingScope = 'personal') {
  let householdId = null;
  if (userId && scope === 'household') {
    const { rows } = await query('SELECT household_id FROM household_members WHERE user_id = $1', [userId]);
    if (rows.length === 0) throw new Error('USER_NOT_IN_HOUSEHOLD');
    householdId = rows[0].household_id;
  }

  const id = ulid();
  await query(
    'INSERT INTO shopping_items (id, name, amount, unit, user_id, household_id) VALUES ($1, $2, $3, $4, $5, $6)',
    [id, name, amount ?? null, unit ?? null, userId || null, householdId]
  );

  const { rows } = await query('SELECT * FROM shopping_items WHERE id = $1', [id]);
  return rows[0];
}

export async function toggleCheck(id: string, userId?: string) {
  let sql: string;
  let params: any[];

  if (!userId) {
    sql = 'SELECT * FROM shopping_items WHERE id = $1 AND user_id IS NULL AND household_id IS NULL';
    params = [id];
  } else {
    sql = `
      SELECT si.* FROM shopping_items si
      LEFT JOIN household_members hm ON si.household_id = hm.household_id
      WHERE si.id = $1 AND (si.user_id = $2 OR hm.user_id = $3)
    `;
    params = [id, userId, userId];
  }

  const { rows } = await query(sql, params);
  if (rows.length === 0) return null;
  const item = rows[0];

  const newVal = !item.checked;
  await query('UPDATE shopping_items SET checked = $1 WHERE id = $2', [newVal, id]);
  return { ...item, checked: newVal };
}

export async function deleteItem(id: string, userId?: string): Promise<boolean> {
  let sql: string;
  let params: any[];

  if (!userId) {
    sql = 'DELETE FROM shopping_items WHERE id = $1 AND user_id IS NULL AND household_id IS NULL';
    params = [id];
  } else {
    sql = `
      DELETE FROM shopping_items
      WHERE id = $1 AND id IN (
        SELECT si.id FROM shopping_items si
        LEFT JOIN household_members hm ON si.household_id = hm.household_id
        WHERE si.user_id = $2 OR hm.user_id = $3
      )
    `;
    params = [id, userId, userId];
  }

  const result = await query(sql, params);
  return (result.rowCount ?? 0) > 0;
}

export async function deleteAll(userId?: string, scope: ShoppingScope = 'personal'): Promise<number> {
  let sql: string;
  let params: any[];

  if (!userId) {
    sql = 'DELETE FROM shopping_items WHERE user_id IS NULL AND household_id IS NULL';
    params = [];
  } else if (scope === 'household') {
    sql = 'DELETE FROM shopping_items WHERE household_id IN (SELECT household_id FROM household_members WHERE user_id = $1)';
    params = [userId];
  } else {
    sql = 'DELETE FROM shopping_items WHERE user_id = $1 AND household_id IS NULL';
    params = [userId];
  }

  const result = await query(sql, params);
  return result.rowCount ?? 0;
}

export async function deleteChecked(userId?: string, scope: ShoppingScope = 'personal'): Promise<number> {
  let sql: string;
  let params: any[];

  if (!userId) {
    sql = 'DELETE FROM shopping_items WHERE checked = TRUE AND user_id IS NULL AND household_id IS NULL';
    params = [];
  } else if (scope === 'household') {
    sql = 'DELETE FROM shopping_items WHERE checked = TRUE AND household_id IN (SELECT household_id FROM household_members WHERE user_id = $1)';
    params = [userId];
  } else {
    sql = 'DELETE FROM shopping_items WHERE checked = TRUE AND user_id = $1 AND household_id IS NULL';
    params = [userId];
  }

  const result = await query(sql, params);
  return result.rowCount ?? 0;
}
