-- ============================================
-- rioCata - Tests de Casos Límite (Edge Cases)
-- ============================================
-- Tests que verifican comportamiento en casos límite
-- y situaciones especiales
-- ============================================

\echo '=========================================='
\echo 'Tests de Casos Límite'
\echo '=========================================='
\echo ''

-- ============================================
-- TEST: Arrays vacíos son válidos
-- ============================================
\echo '[EDGE 1] Validando arrays vacíos...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_part_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_edge1@test.com', 'Test User');

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-EDGE-1', 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_muestra_id, test_sesion_id, 'TEST-M1');

  -- Test: evaluación con todos los arrays vacíos
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades,
      tazas_no_uniformes, tazas_defectuosas,
      sensacion_en_boca, gustos_predominantes
    ) VALUES (
      test_muestra_id, test_part_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      ARRAY[]::smallint[], ARRAY[]::smallint[],
      ARRAY[]::text[], ARRAY[]::text[]
    );
    RAISE NOTICE '  ✓ Acepta arrays vacíos correctamente';
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó arrays vacíos: %', SQLERRM;
  END;

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

  RAISE NOTICE '✓ Arrays vacíos funcionan correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Campos opcionales en NULL
-- ============================================
\echo '[EDGE 2] Validando campos opcionales en NULL...'

DO $$
DECLARE
  test_sesion_id uuid := gen_random_uuid();
  test_user_id uuid := gen_random_uuid();
  test_part_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_edge2@test.com', 'Test User');

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-EDGE-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_muestra_id, test_sesion_id, 'TEST-M2');

  -- Test: evaluación con campos opcionales en NULL
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades,
      defecto, otras_notas
    ) VALUES (
      test_muestra_id, test_part_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      NULL, NULL
    );
    RAISE NOTICE '  ✓ Acepta campos opcionales NULL';
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó campos NULL: %', SQLERRM;
  END;

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

  RAISE NOTICE '✓ Campos opcionales NULL funcionan correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: JSONB con solo un parámetro
-- ============================================
\echo '[EDGE 3] Validando intensidades con un solo parámetro...'

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

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-EDGE-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_muestra_id, test_sesion_id, 'TEST-M3');

  -- Test: solo un parámetro en intensidades
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_part_id,
      '{"fragancia":{"descriptiva":5,"afectiva":7}}'::jsonb
    ) RETURNING puntaje_final INTO puntaje;

    IF puntaje = 7 THEN
      RAISE NOTICE '  ✓ Acepta un solo parámetro y calcula puntaje correcto: %', puntaje;
    ELSE
      RAISE EXCEPTION '  ✗ Puntaje incorrecto con un parámetro: % (esperado: 7)', puntaje;
    END IF;
  EXCEPTION WHEN check_violation THEN
    RAISE EXCEPTION '  ✗ Rechazó un solo parámetro: %', SQLERRM;
  END;

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

  RAISE NOTICE '✓ Un solo parámetro funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Valores descriptivos NULL con afectivos presentes
-- ============================================
\echo '[EDGE 4] Validando descriptiva NULL con afectiva presente...'

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

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-EDGE-4', 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_muestra_id, test_sesion_id, 'TEST-M4');

  -- Test: impresionGlobal con descriptiva NULL (caso común)
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_part_id,
      '{"impresionGlobal":{"descriptiva":null,"afectiva":8}}'::jsonb
    ) RETURNING puntaje_final INTO puntaje;

    IF puntaje = 8 THEN
      RAISE NOTICE '  ✓ Acepta descriptiva NULL y calcula puntaje correcto: %', puntaje;
    ELSE
      RAISE EXCEPTION '  ✗ Puntaje incorrecto: % (esperado: 8)', puntaje;
    END IF;
  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó descriptiva NULL: %', SQLERRM;
  END;

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

  RAISE NOTICE '✓ Descriptiva NULL funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: JSONB arrays con múltiples elementos
-- ============================================
\echo '[EDGE 5] Validando arrays JSONB con múltiples notas...'

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

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-EDGE-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_muestra_id, test_sesion_id, 'TEST-M5');

  -- Test: múltiples notas de fragancia/aroma
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades,
      fragancia_aroma_notas, sabor_notas
    ) VALUES (
      test_muestra_id, test_part_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      '[
        {"categoria":"Afrutado","subcategoria":"Cítricos","notaEspecifica":"Naranja"},
        {"categoria":"Floral","subcategoria":"Jazmín","notaEspecifica":null},
        {"categoria":"Especiado","subcategoria":"Canela","notaEspecifica":"Canela dulce"}
      ]'::jsonb,
      '[
        {"categoria":"Chocolatado","subcategoria":"Chocolate negro","notaEspecifica":null},
        {"categoria":"Nueces","subcategoria":"Almendra","notaEspecifica":"Tostada"}
      ]'::jsonb
    );

    -- Verificar que se guardaron correctamente
    SELECT jsonb_array_length(fragancia_aroma_notas)
    INTO notas_count
    FROM evaluacion
    WHERE muestra_id = test_muestra_id;

    IF notas_count = 3 THEN
      RAISE NOTICE '  ✓ Acepta múltiples notas de fragancia (3)';
    ELSE
      RAISE EXCEPTION '  ✗ Cantidad incorrecta de notas: % (esperado: 3)', notas_count;
    END IF;

    SELECT jsonb_array_length(sabor_notas)
    INTO notas_count
    FROM evaluacion
    WHERE muestra_id = test_muestra_id;

    IF notas_count = 2 THEN
      RAISE NOTICE '  ✓ Acepta múltiples notas de sabor (2)';
    ELSE
      RAISE EXCEPTION '  ✗ Cantidad incorrecta de notas: % (esperado: 2)', notas_count;
    END IF;

  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó múltiples notas: %', SQLERRM;
  END;

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

  RAISE NOTICE '✓ Arrays JSONB con múltiples elementos funcionan correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Evaluación mínima válida (solo intensidades requeridas)
-- ============================================
\echo '[EDGE 6] Validando evaluación mínima válida...'

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

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-EDGE-6', 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_muestra_id, test_sesion_id, 'TEST-M6');

  -- Test: solo intensidades (campo obligatorio), todo lo demás default/NULL
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      test_muestra_id, test_part_id,
      '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb
    ) RETURNING id INTO eval_id;

    -- Verificar que los defaults se aplicaron
    PERFORM 1
    FROM evaluacion
    WHERE id = eval_id
      AND fragancia_aroma_notas = '[]'::jsonb
      AND sabor_notas = '[]'::jsonb
      AND tazas_no_uniformes = ARRAY[]::smallint[]
      AND tazas_defectuosas = ARRAY[]::smallint[]
      AND sensacion_en_boca = ARRAY[]::text[]
      AND gustos_predominantes = ARRAY[]::text[]
      AND defecto IS NULL
      AND otras_notas IS NULL;

    IF FOUND THEN
      RAISE NOTICE '  ✓ Evaluación mínima válida con defaults correctos';
    ELSE
      RAISE EXCEPTION '  ✗ Defaults no se aplicaron correctamente';
    END IF;

  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Rechazó evaluación mínima: %', SQLERRM;
  END;

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

  RAISE NOTICE '✓ Evaluación mínima válida funciona correctamente';
END $$;

\echo ''

-- ============================================
-- TEST: Texto largo en otras_notas
-- ============================================
\echo '[EDGE 7] Validando texto largo en otras_notas...'

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

  INSERT INTO sesion (id, codigo, fecha)
  VALUES (test_sesion_id, 'TEST-EDGE-7', 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_muestra_id, test_sesion_id, 'TEST-M7');

  -- Generar texto de 1000 caracteres
  long_text := repeat('Este es un texto largo con muchos detalles sobre la catación. ', 20);

  -- Test: insertar texto largo
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, otras_notas
    ) VALUES (
      test_muestra_id, test_part_id,
      '{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
      long_text
    );

    SELECT otras_notas INTO stored_text
    FROM evaluacion
    WHERE muestra_id = test_muestra_id;

    IF stored_text = long_text THEN
      RAISE NOTICE '  ✓ Acepta y almacena texto largo (% caracteres)', length(stored_text);
    ELSE
      RAISE EXCEPTION '  ✗ Texto almacenado no coincide';
    END IF;

  EXCEPTION WHEN OTHERS THEN
    RAISE EXCEPTION '  ✗ Falló con texto largo: %', SQLERRM;
  END;

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

  RAISE NOTICE '✓ Texto largo funciona correctamente';
END $$;

\echo ''

\echo '=========================================='
\echo 'Tests de Casos Límite completados'
\echo '=========================================='
