-- ============================================
-- rioCata - Tests de Queries Típicas
-- ============================================
-- Tests que verifican queries comunes con datos
-- generados dinámicamente y validaciones específicas
-- ============================================

\echo '=========================================='
\echo 'Tests de Queries Típicas'
\echo '=========================================='
\echo ''

-- ============================================
-- TEST: Query promedio de parámetro afectivo
-- ============================================
\echo '[QUERY 1] Probando query: Promedio de parámetro afectivo...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user1_id uuid := gen_random_uuid();
  test_user2_id uuid := gen_random_uuid();
  test_part1_id uuid := gen_random_uuid();
  test_part2_id uuid := gen_random_uuid();
  test_muestra_id uuid := gen_random_uuid();
  avg_dulzor numeric;
  expected_avg numeric := 7.5; -- (5 + 10) / 2
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre) VALUES
    (test_user1_id, 'test_query1_u1@test.com', 'User 1'),
    (test_user2_id, 'test_query1_u2@test.com', 'User 2');

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-QUERY-1', CURRENT_DATE);

  INSERT INTO sesion_participante (id, sesion_id, catador_id) VALUES
    (test_part1_id, test_sesion_id, test_user1_id),
    (test_part2_id, test_sesion_id, test_user2_id);

  INSERT INTO muestra (id, sesion_id, codigo)
  VALUES (test_muestra_id, test_sesion_id, 'TEST-M1');

  -- Crear 2 evaluaciones con dulzor 5 y 10
  INSERT INTO evaluacion (muestra_id, sesion_participante_id, intensidades) VALUES
    (test_muestra_id, test_part1_id,
     '{"dulzor":{"descriptiva":5,"afectiva":5}}'::jsonb),
    (test_muestra_id, test_part2_id,
     '{"dulzor":{"descriptiva":10,"afectiva":10}}'::jsonb);

  -- Ejecutar query
  SELECT AVG(((e.intensidades->'dulzor'->>'afectiva')::int))
  INTO avg_dulzor
  FROM sesion s
  JOIN muestra m ON m.sesion_id = s.id
  JOIN evaluacion e ON e.muestra_id = m.id
  WHERE s.id = test_sesion_id;

  -- Validar resultado
  IF avg_dulzor = expected_avg THEN
    RAISE NOTICE '  ✓ Promedio calculado correctamente: % (esperado: %)',
      avg_dulzor, expected_avg;
  ELSE
    RAISE EXCEPTION '  ✗ Promedio incorrecto: % (esperado: %)',
      avg_dulzor, expected_avg;
  END IF;

  -- Cleanup
  DELETE FROM sesion WHERE id = test_sesion_id;
  DELETE FROM auth.users WHERE id IN (test_user1_id, test_user2_id);

  RAISE NOTICE '✓ Query promedio de parámetro afectivo funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Query buscar por defecto específico
-- ============================================
\echo '[QUERY 2] Probando query: Buscar evaluaciones con defecto específico...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_part_id uuid := gen_random_uuid();
  test_muestra1_id uuid := gen_random_uuid();
  test_muestra2_id uuid := gen_random_uuid();
  count_fenolico int;
  count_mohoso int;
  expected_fenolico int := 2;
  expected_mohoso int := 1;
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_query2@test.com', 'Test User');

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-QUERY-2', CURRENT_DATE);

  INSERT INTO sesion_participante (id, sesion_id, catador_id)
  VALUES (test_part_id, test_sesion_id, test_user_id);

  INSERT INTO muestra (id, sesion_id, codigo) VALUES
    (test_muestra1_id, test_sesion_id, 'TEST-M1'),
    (test_muestra2_id, test_sesion_id, 'TEST-M2');

  -- Crear 2 evaluaciones con defecto Fenólico y 1 con Mohoso
  INSERT INTO evaluacion (muestra_id, sesion_participante_id, intensidades, defecto)
  SELECT test_muestra1_id, test_part_id,
         '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
         'Fenólico'::defecto_tipo
  UNION ALL
  SELECT test_muestra2_id, test_part_id,
         '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
         'Fenólico'::defecto_tipo;

  -- Insertar una con Mohoso en nueva muestra
  DELETE FROM muestra WHERE id = test_muestra1_id;
  INSERT INTO muestra (id, sesion_id, codigo)
  VALUES (test_muestra1_id, test_sesion_id, 'TEST-M3');

  INSERT INTO evaluacion (muestra_id, sesion_participante_id, intensidades, defecto)
  VALUES (test_muestra1_id, test_part_id,
          '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
          'Mohoso'::defecto_tipo);

  -- Query para Fenólico
  SELECT COUNT(*) INTO count_fenolico
  FROM evaluacion
  WHERE defecto = 'Fenólico';

  -- Query para Mohoso
  SELECT COUNT(*) INTO count_mohoso
  FROM evaluacion
  WHERE defecto = 'Mohoso';

  -- Validar
  IF count_fenolico = expected_fenolico AND count_mohoso = expected_mohoso THEN
    RAISE NOTICE '  ✓ Búsqueda por defecto correcta: Fenólico=%, Mohoso=%',
      count_fenolico, count_mohoso;
  ELSE
    RAISE EXCEPTION '  ✗ Búsqueda incorrecta: Fenólico=% (esp: %), Mohoso=% (esp: %)',
      count_fenolico, expected_fenolico, count_mohoso, expected_mohoso;
  END IF;

  -- Cleanup
  DELETE FROM sesion WHERE id = test_sesion_id;
  DELETE FROM auth.users WHERE id = test_user_id;

  RAISE NOTICE '✓ Query buscar por defecto funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Query buscar taza defectuosa con operador @>
-- ============================================
\echo '[QUERY 3] Probando query: Buscar taza defectuosa específica (índice GIN)...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_part_id uuid := gen_random_uuid();
  test_muestra1_id uuid := gen_random_uuid();
  test_muestra2_id uuid := gen_random_uuid();
  test_muestra3_id uuid := gen_random_uuid();
  count_taza5 int;
  count_taza3 int;
  expected_taza5 int := 2;
  expected_taza3 int := 1;
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_query3@test.com', 'Test User');

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-QUERY-3', CURRENT_DATE);

  INSERT INTO sesion_participante (id, sesion_id, catador_id)
  VALUES (test_part_id, test_sesion_id, test_user_id);

  INSERT INTO muestra (id, sesion_id, codigo) VALUES
    (test_muestra1_id, test_sesion_id, 'TEST-M1'),
    (test_muestra2_id, test_sesion_id, 'TEST-M2'),
    (test_muestra3_id, test_sesion_id, 'TEST-M3');

  -- Crear evaluaciones con tazas defectuosas
  INSERT INTO evaluacion (muestra_id, sesion_participante_id, intensidades, tazas_defectuosas) VALUES
    (test_muestra1_id, test_part_id,
     '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
     ARRAY[5]::smallint[]),
    (test_muestra2_id, test_part_id,
     '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
     ARRAY[3, 5]::smallint[]),
    (test_muestra3_id, test_part_id,
     '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
     ARRAY[1, 2]::smallint[]);

  -- Query usando operador @> (debe usar índice GIN)
  -- Filtrar solo por evaluaciones de esta sesión de prueba
  SELECT COUNT(*) INTO count_taza5
  FROM evaluacion e
  JOIN muestra m ON m.id = e.muestra_id
  WHERE m.sesion_id = test_sesion_id
    AND e.tazas_defectuosas @> ARRAY[5]::smallint[];

  SELECT COUNT(*) INTO count_taza3
  FROM evaluacion e
  JOIN muestra m ON m.id = e.muestra_id
  WHERE m.sesion_id = test_sesion_id
    AND e.tazas_defectuosas @> ARRAY[3]::smallint[];

  -- Validar
  IF count_taza5 = expected_taza5 AND count_taza3 = expected_taza3 THEN
    RAISE NOTICE '  ✓ Operador @> funciona correctamente: taza5=%, taza3=%',
      count_taza5, count_taza3;
  ELSE
    RAISE EXCEPTION '  ✗ Operador @> incorrecto: taza5=% (esp: %), taza3=% (esp: %)',
      count_taza5, expected_taza5, count_taza3, expected_taza3;
  END IF;

  -- Cleanup
  DELETE FROM sesion WHERE id = test_sesion_id;
  DELETE FROM auth.users WHERE id = test_user_id;

  RAISE NOTICE '✓ Query con operador @> funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Query top muestras por puntaje
-- ============================================
\echo '[QUERY 4] Probando query: Top muestras por puntaje final...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_part_id uuid := gen_random_uuid();
  test_muestra1_id uuid := gen_random_uuid();
  test_muestra2_id uuid := gen_random_uuid();
  test_muestra3_id uuid := gen_random_uuid();
  top_muestra text;
  top_puntaje int;
  expected_muestra text := 'HIGH';
  expected_puntaje int := 80;
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_query4@test.com', 'Test User');

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-QUERY-4', CURRENT_DATE);

  INSERT INTO sesion_participante (id, sesion_id, catador_id)
  VALUES (test_part_id, test_sesion_id, test_user_id);

  -- Crear 3 muestras con diferentes puntajes
  INSERT INTO muestra (id, sesion_id, codigo) VALUES
    (test_muestra1_id, test_sesion_id, 'LOW'),
    (test_muestra2_id, test_sesion_id, 'MID'),
    (test_muestra3_id, test_sesion_id, 'HIGH');

  -- Evaluaciones con puntajes 20, 50, 80
  INSERT INTO evaluacion (muestra_id, sesion_participante_id, intensidades) VALUES
    (test_muestra1_id, test_part_id,
     '{"fragancia":{"descriptiva":1,"afectiva":2},"aroma":{"descriptiva":1,"afectiva":3},"sabor":{"descriptiva":1,"afectiva":2},"saborResidual":{"descriptiva":1,"afectiva":3},"acidez":{"descriptiva":1,"afectiva":3},"dulzor":{"descriptiva":1,"afectiva":2},"sensacionBoca":{"descriptiva":1,"afectiva":3},"impresionGlobal":{"afectiva":2}}'::jsonb),
    (test_muestra2_id, test_part_id,
     '{"fragancia":{"descriptiva":5,"afectiva":6},"aroma":{"descriptiva":5,"afectiva":6},"sabor":{"descriptiva":5,"afectiva":7},"saborResidual":{"descriptiva":5,"afectiva":6},"acidez":{"descriptiva":5,"afectiva":6},"dulzor":{"descriptiva":5,"afectiva":7},"sensacionBoca":{"descriptiva":5,"afectiva":6},"impresionGlobal":{"afectiva":6}}'::jsonb),
    (test_muestra3_id, test_part_id,
     '{"fragancia":{"descriptiva":10,"afectiva":10},"aroma":{"descriptiva":10,"afectiva":10},"sabor":{"descriptiva":10,"afectiva":10},"saborResidual":{"descriptiva":10,"afectiva":10},"acidez":{"descriptiva":10,"afectiva":10},"dulzor":{"descriptiva":10,"afectiva":10},"sensacionBoca":{"descriptiva":10,"afectiva":10},"impresionGlobal":{"afectiva":10}}'::jsonb);

  -- Query top 1
  SELECT m.codigo, e.puntaje_final
  INTO top_muestra, top_puntaje
  FROM muestra m
  JOIN evaluacion e ON e.muestra_id = m.id
  JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
  WHERE m.sesion_id = test_sesion_id
  ORDER BY e.puntaje_final DESC
  LIMIT 1;

  -- Validar
  IF top_muestra = expected_muestra AND top_puntaje = expected_puntaje THEN
    RAISE NOTICE '  ✓ Top muestra correcta: % con puntaje %',
      top_muestra, top_puntaje;
  ELSE
    RAISE EXCEPTION '  ✗ Top muestra incorrecta: % (esp: %), puntaje: % (esp: %)',
      top_muestra, expected_muestra, top_puntaje, expected_puntaje;
  END IF;

  -- Cleanup
  DELETE FROM sesion WHERE id = test_sesion_id;
  DELETE FROM auth.users WHERE id = test_user_id;

  RAISE NOTICE '✓ Query top muestras funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Query filtrar por acidez alta (índice funcional)
-- ============================================
\echo '[QUERY 5] Probando query: Filtrar por acidez afectiva >= 8...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_part_id uuid := gen_random_uuid();
  test_muestra1_id uuid := gen_random_uuid();
  test_muestra2_id uuid := gen_random_uuid();
  test_muestra3_id uuid := gen_random_uuid();
  count_high_acidez int;
  expected_count int := 2;
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_query5@test.com', 'Test User');

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-QUERY-5', CURRENT_DATE);

  INSERT INTO sesion_participante (id, sesion_id, catador_id)
  VALUES (test_part_id, test_sesion_id, test_user_id);

  INSERT INTO muestra (id, sesion_id, codigo) VALUES
    (test_muestra1_id, test_sesion_id, 'TEST-M1'),
    (test_muestra2_id, test_sesion_id, 'TEST-M2'),
    (test_muestra3_id, test_sesion_id, 'TEST-M3');

  -- Crear evaluaciones con acidez 5, 8, 10
  INSERT INTO evaluacion (muestra_id, sesion_participante_id, intensidades) VALUES
    (test_muestra1_id, test_part_id,
     '{"acidez":{"descriptiva":5,"afectiva":5}}'::jsonb),
    (test_muestra2_id, test_part_id,
     '{"acidez":{"descriptiva":8,"afectiva":8}}'::jsonb),
    (test_muestra3_id, test_part_id,
     '{"acidez":{"descriptiva":10,"afectiva":10}}'::jsonb);

  -- Query con índice funcional
  -- Filtrar solo por evaluaciones de esta sesión de prueba
  SELECT COUNT(*) INTO count_high_acidez
  FROM evaluacion e
  JOIN muestra m ON m.id = e.muestra_id
  WHERE m.sesion_id = test_sesion_id
    AND ((e.intensidades->'acidez'->>'afectiva')::int) >= 8;

  -- Validar
  IF count_high_acidez = expected_count THEN
    RAISE NOTICE '  ✓ Filtro por acidez >= 8 correcto: % evaluaciones',
      count_high_acidez;
  ELSE
    RAISE EXCEPTION '  ✗ Filtro incorrecto: % (esperado: %)',
      count_high_acidez, expected_count;
  END IF;

  -- Cleanup
  DELETE FROM sesion WHERE id = test_sesion_id;
  DELETE FROM auth.users WHERE id = test_user_id;

  RAISE NOTICE '✓ Query con filtro por parámetro JSONB funciona correctamente';
END $$;

\echo ''

\echo '=========================================='
\echo 'Tests de Queries completados'
\echo '=========================================='
