-- ============================================
-- rioCata - Tests de Constraints
-- ============================================
-- Tests que verifican la validación de constraints
-- de la base de datos sin depender de datos hardcodeados
-- ============================================

\echo '=========================================='
\echo 'Tests de Constraints'
\echo '=========================================='
\echo ''

-- ============================================
-- TEST: Constraint tazas_no_uniformes (solo valores 1-5)
-- ============================================
\echo '[CONSTRAINT 1] Validando tazas_no_uniformes (valores 1-5)...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_participante_id uuid := gen_random_uuid();
  test_muestra_id uuid := gen_random_uuid();
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_constraint1@test.com', 'Test User');

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

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

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

  -- Test 1: Valores válidos (1-5) deben pasar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY[1,2,3,4,5]::smallint[]
    );
    RAISE NOTICE '  ✓ Acepta valores válidos 1-5';
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó valores válidos: %', SQLERRM;
  END;

  -- Test 2: Valor inválido (0) debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY[0]::smallint[]
    );
    RAISE EXCEPTION '  ✗ Aceptó valor inválido 0';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente valor 0';
  END;

  -- Test 3: Valor inválido (6) debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY[6]::smallint[]
    );
    RAISE EXCEPTION '  ✗ Aceptó valor inválido 6';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente valor 6';
  END;

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

  RAISE NOTICE '✓ Constraint tazas_no_uniformes funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Constraint tazas_defectuosas (solo valores 1-5)
-- ============================================
\echo '[CONSTRAINT 2] Validando tazas_defectuosas (valores 1-5)...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_participante_id uuid := gen_random_uuid();
  test_muestra_id uuid := gen_random_uuid();
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_constraint2@test.com', 'Test User');

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

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

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

  -- Test: Valor inválido (-1) debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, tazas_defectuosas
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY[-1]::smallint[]
    );
    RAISE EXCEPTION '  ✗ Aceptó valor inválido -1';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente valor -1';
  END;

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

  RAISE NOTICE '✓ Constraint tazas_defectuosas funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Constraint gustos_predominantes (máximo 2 elementos)
-- ============================================
\echo '[CONSTRAINT 3] Validando gustos_predominantes (máximo 2 elementos)...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_participante_id uuid := gen_random_uuid();
  test_muestra_id uuid := gen_random_uuid();
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_constraint3@test.com', 'Test User');

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

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

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

  -- Test 1: 0 elementos debe pasar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, gustos_predominantes
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY[]::text[]
    );
    RAISE NOTICE '  ✓ Acepta 0 elementos';
    DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó 0 elementos: %', SQLERRM;
  END;

  -- Test 2: 1 elemento debe pasar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, gustos_predominantes
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY['Dulce']::text[]
    );
    RAISE NOTICE '  ✓ Acepta 1 elemento';
    DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó 1 elemento: %', SQLERRM;
  END;

  -- Test 3: 2 elementos debe pasar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, gustos_predominantes
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY['Dulce', 'Ácido']::text[]
    );
    RAISE NOTICE '  ✓ Acepta 2 elementos';
    DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó 2 elementos: %', SQLERRM;
  END;

  -- Test 4: 3 elementos debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, gustos_predominantes
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY['Dulce', 'Ácido', 'Amargo']::text[]
    );
    RAISE EXCEPTION '  ✗ Aceptó 3 elementos';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente 3 elementos';
  END;

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

  RAISE NOTICE '✓ Constraint gustos_predominantes funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Constraint sensacion_en_boca (valores permitidos)
-- ============================================
\echo '[CONSTRAINT 4] Validando sensacion_en_boca (valores permitidos)...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_participante_id uuid := gen_random_uuid();
  test_muestra_id uuid := gen_random_uuid();
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_constraint4@test.com', 'Test User');

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

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

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

  -- Test 1: Valores válidos deben pasar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, sensacion_en_boca
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY['Áspero', 'Suave', 'Aceitoso', 'Metálico', 'Astringente']::text[]
    );
    RAISE NOTICE '  ✓ Acepta todos los valores permitidos';
    DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó valores válidos: %', SQLERRM;
  END;

  -- Test 2: Valor inválido debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, sensacion_en_boca
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY['Raro', 'Extraño']::text[]
    );
    RAISE EXCEPTION '  ✗ Aceptó valores inválidos';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente valores inválidos';
  END;

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

  RAISE NOTICE '✓ Constraint sensacion_en_boca funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Constraint rangos de intensidades
-- ============================================
\echo '[CONSTRAINT 5] Validando rangos intensidades (descriptiva 1-15, afectiva 1-10)...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_participante_id uuid := gen_random_uuid();
  test_muestra_id uuid := gen_random_uuid();
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_constraint5@test.com', 'Test User');

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

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

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

  -- Test 1: Valores en límites válidos (1 y 15 para descriptiva)
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":1,"afectiva":1},"aroma":{"descriptiva":15,"afectiva":10}}'::jsonb
    );
    RAISE NOTICE '  ✓ Acepta límites válidos (descriptiva: 1 y 15, afectiva: 1 y 10)';
    DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó límites válidos: %', SQLERRM;
  END;

  -- Test 2: descriptiva < 1 debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":0,"afectiva":5}}'::jsonb
    );
    RAISE EXCEPTION '  ✗ Aceptó descriptiva=0';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente descriptiva < 1';
  END;

  -- Test 3: descriptiva > 15 debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":16,"afectiva":5}}'::jsonb
    );
    RAISE EXCEPTION '  ✗ Aceptó descriptiva=16';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente descriptiva > 15';
  END;

  -- Test 4: afectiva < 1 debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":0}}'::jsonb
    );
    RAISE EXCEPTION '  ✗ Aceptó afectiva=0';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente afectiva < 1';
  END;

  -- Test 5: afectiva > 10 debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":11}}'::jsonb
    );
    RAISE EXCEPTION '  ✗ Aceptó afectiva=11';
  EXCEPTION WHEN check_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente afectiva > 10';
  END;

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

  RAISE NOTICE '✓ Constraint rangos de intensidades funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Constraint UNIQUE (una evaluación por participante/muestra)
-- ============================================
\echo '[CONSTRAINT 6] Validando constraint UNIQUE (una evaluación por participante/muestra)...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_participante_id uuid := gen_random_uuid();
  test_muestra_id uuid := gen_random_uuid();
BEGIN
  -- Crear datos de prueba
  INSERT INTO auth.users (id, email, nombre)
  VALUES (test_user_id, 'test_constraint6@test.com', 'Test User');

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

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

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

  -- Test 1: Primera evaluación debe pasar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb
    );
    RAISE NOTICE '  ✓ Acepta primera evaluación';
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó primera evaluación: %', SQLERRM;
  END;

  -- Test 2: Segunda evaluación de mismo participante/muestra debe fallar
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_participante_id,
      '{"fragancia":{"descriptiva":7,"afectiva":8}}'::jsonb
    );
    RAISE EXCEPTION '  ✗ Permitió evaluación duplicada';
  EXCEPTION WHEN unique_violation THEN
    RAISE NOTICE '  ✓ Rechaza correctamente evaluación duplicada';
  END;

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

  RAISE NOTICE '✓ Constraint UNIQUE funciona correctamente';
END $$;

\echo ''
\echo '=========================================='
\echo 'Tests de Constraints completados'
\echo '=========================================='
