-- ============================================
-- rioCata - Tests de Validación
-- ============================================
-- Este script ejecuta tests para validar:
-- 1. Estructura de tablas y constraints
-- 2. Triggers (updated_at, puntaje_final)
-- 3. Validaciones de arrays y JSONB
-- 4. Queries típicas
-- 5. Funciones auxiliares
-- ============================================

\echo '=========================================='
\echo 'rioCata - Test Suite'
\echo '=========================================='
\echo ''

-- ============================================
-- TEST 1: Verificar que las tablas existen
-- ============================================
\echo '[TEST 1] Verificando existencia de tablas...'

DO $$
DECLARE
  tabla_count int;
BEGIN
  SELECT COUNT(*) INTO tabla_count
  FROM information_schema.tables
  WHERE table_schema = 'public'
    AND table_name IN ('sesion', 'sesion_participante', 'muestra', 'evaluacion');

  IF tabla_count = 4 THEN
    RAISE NOTICE '✓ Todas las tablas principales existen (4/4)';
  ELSE
    RAISE EXCEPTION '✗ Faltan tablas. Encontradas: %/4', tabla_count;
  END IF;

  -- Verificar tabla auth.users
  SELECT COUNT(*) INTO tabla_count
  FROM information_schema.tables
  WHERE table_schema = 'auth' AND table_name = 'users';

  IF tabla_count = 1 THEN
    RAISE NOTICE '✓ Tabla auth.users existe';
  ELSE
    RAISE EXCEPTION '✗ Tabla auth.users no existe';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 2: Verificar tipo ENUM defecto_tipo
-- ============================================
\echo '[TEST 2] Verificando tipo ENUM defecto_tipo...'

DO $$
DECLARE
  enum_exists boolean;
BEGIN
  SELECT EXISTS (
    SELECT 1 FROM pg_type WHERE typname = 'defecto_tipo'
  ) INTO enum_exists;

  IF enum_exists THEN
    RAISE NOTICE '✓ Tipo ENUM defecto_tipo existe';
  ELSE
    RAISE EXCEPTION '✗ Tipo ENUM defecto_tipo no existe';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 3: Verificar triggers
-- ============================================
\echo '[TEST 3] Verificando triggers...'

DO $$
DECLARE
  trigger_count int;
BEGIN
  SELECT COUNT(*) INTO trigger_count
  FROM information_schema.triggers
  WHERE trigger_name IN ('trg_eval_updated_at', 'trg_eval_score_bi');

  IF trigger_count = 2 THEN
    RAISE NOTICE '✓ Todos los triggers existen (2/2)';
  ELSE
    RAISE EXCEPTION '✗ Faltan triggers. Encontrados: %/2', trigger_count;
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 4: Verificar índices
-- ============================================
\echo '[TEST 4] Verificando índices...'

DO $$
DECLARE
  index_count int;
BEGIN
  SELECT COUNT(*) INTO index_count
  FROM pg_indexes
  WHERE schemaname = 'public'
    AND indexname LIKE 'idx_%';

  IF index_count >= 15 THEN
    RAISE NOTICE '✓ Índices creados correctamente (% encontrados)', index_count;
  ELSE
    RAISE WARNING '⚠ Se esperaban al menos 15 índices, se encontraron: %', index_count;
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 5: Test de constraint - tazas_no_uniformes válidas
-- ============================================
\echo '[TEST 5] Validando constraint tazas_no_uniformes (valores 1-5)...'

DO $$
BEGIN
  -- Intentar insertar valor inválido (6)
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes
    ) VALUES (
      'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
      'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
      '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb,
      ARRAY[6]::smallint[]
    );
    RAISE EXCEPTION '✗ El constraint tazas_no_uniformes NO funcionó (aceptó valor 6)';
  EXCEPTION
    WHEN check_violation THEN
      RAISE NOTICE '✓ Constraint tazas_no_uniformes funciona correctamente';
  END;
END $$;

\echo ''

-- ============================================
-- TEST 6: Test de constraint - gustos_predominantes (máximo 2)
-- ============================================
\echo '[TEST 6] Validando constraint gustos_predominantes (máximo 2 elementos)...'

DO $$
BEGIN
  -- Intentar insertar 3 gustos (debería fallar)
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, gustos_predominantes
    ) VALUES (
      'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
      'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
      '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb,
      ARRAY['Ácido', 'Dulce', 'Amargo']::text[]
    );
    RAISE EXCEPTION '✗ El constraint gustos_predominantes NO funcionó (aceptó 3 elementos)';
  EXCEPTION
    WHEN check_violation THEN
      RAISE NOTICE '✓ Constraint gustos_predominantes funciona correctamente';
  END;
END $$;

\echo ''

-- ============================================
-- TEST 7: Test de constraint - sensacion_en_boca (valores válidos)
-- ============================================
\echo '[TEST 7] Validando constraint sensacion_en_boca (valores permitidos)...'

DO $$
BEGIN
  -- Intentar insertar valor no permitido
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades, sensacion_en_boca
    ) VALUES (
      'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
      'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
      '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb,
      ARRAY['Raro', 'Extraño']::text[]
    );
    RAISE EXCEPTION '✗ El constraint sensacion_en_boca NO funcionó';
  EXCEPTION
    WHEN check_violation THEN
      RAISE NOTICE '✓ Constraint sensacion_en_boca funciona correctamente';
  END;
END $$;

\echo ''

-- ============================================
-- TEST 8: Test de constraint - rangos de intensidades
-- ============================================
\echo '[TEST 8] Validando constraint rangos de intensidades (descriptiva 1-15, afectiva 1-10)...'

DO $$
BEGIN
  -- Intentar insertar descriptiva > 15
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
      'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
      '{"fragancia":{"descriptiva":20,"afectiva":5}}'::jsonb
    );
    RAISE EXCEPTION '✗ El constraint de rangos NO funcionó (aceptó descriptiva=20)';
  EXCEPTION
    WHEN check_violation THEN
      RAISE NOTICE '✓ Constraint rangos de intensidades funciona (descriptiva)';
  END;

  -- Intentar insertar afectiva > 10
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
      'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
      '{"fragancia":{"descriptiva":5,"afectiva":15}}'::jsonb
    );
    RAISE EXCEPTION '✗ El constraint de rangos NO funcionó (aceptó afectiva=15)';
  EXCEPTION
    WHEN check_violation THEN
      RAISE NOTICE '✓ Constraint rangos de intensidades funciona (afectiva)';
  END;
END $$;

\echo ''

-- ============================================
-- TEST 9: Test de trigger - puntaje_final se calcula automáticamente
-- ============================================
\echo '[TEST 9] Validando trigger de cálculo automático de puntaje_final...'

DO $$
DECLARE
  puntaje_calculado int;
  puntaje_esperado int := 75; -- Suma de afectivos: 9+9+10+9+9+10+9+10 = 75
BEGIN
  -- Verificar evaluación existente
  SELECT puntaje_final INTO puntaje_calculado
  FROM evaluacion
  WHERE muestra_id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
    AND sesion_participante_id = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb';

  IF puntaje_calculado = puntaje_esperado THEN
    RAISE NOTICE '✓ Trigger puntaje_final funciona correctamente (% = %)', puntaje_calculado, puntaje_esperado;
  ELSE
    RAISE EXCEPTION '✗ Puntaje calculado (%) no coincide con esperado (%)', puntaje_calculado, puntaje_esperado;
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 10: Test de constraint UNIQUE - una evaluación por participante por muestra
-- ============================================
\echo '[TEST 10] Validando constraint UNIQUE (una evaluación por participante/muestra)...'

DO $$
BEGIN
  -- Intentar insertar evaluación duplicada
  BEGIN
    INSERT INTO evaluacion (
      muestra_id, sesion_participante_id, intensidades
    ) VALUES (
      'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee',
      'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
      '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb
    );
    RAISE EXCEPTION '✗ El constraint UNIQUE NO funcionó (permitió duplicado)';
  EXCEPTION
    WHEN unique_violation THEN
      RAISE NOTICE '✓ Constraint UNIQUE funciona correctamente';
  END;
END $$;

\echo ''

-- ============================================
-- TEST 11: Query típica - Promedio de parámetro afectivo
-- ============================================
\echo '[TEST 11] Probando query: Promedio de dulzor afectivo por sesión...'

DO $$
DECLARE
  avg_dulzor numeric;
BEGIN
  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 = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa';

  IF avg_dulzor IS NOT NULL THEN
    RAISE NOTICE '✓ Query promedio funciona. Dulzor promedio: %', ROUND(avg_dulzor, 2);
  ELSE
    RAISE EXCEPTION '✗ Query promedio falló';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 12: Query típica - Buscar por defecto
-- ============================================
\echo '[TEST 12] Probando query: Buscar evaluaciones con defecto Fenólico...'

DO $$
DECLARE
  defecto_count int;
BEGIN
  SELECT COUNT(*) INTO defecto_count
  FROM evaluacion
  WHERE defecto = 'Fenólico';

  IF defecto_count > 0 THEN
    RAISE NOTICE '✓ Query por defecto funciona. Evaluaciones con defecto Fenólico: %', defecto_count;
  ELSE
    RAISE WARNING '⚠ No se encontraron evaluaciones con defecto Fenólico (puede ser normal)';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 13: Query típica - Buscar por taza defectuosa específica
-- ============================================
\echo '[TEST 13] Probando query: Buscar evaluaciones donde taza 5 fue defectuosa...'

DO $$
DECLARE
  taza_count int;
BEGIN
  SELECT COUNT(*) INTO taza_count
  FROM evaluacion
  WHERE tazas_defectuosas @> ARRAY[5]::smallint[];

  IF taza_count > 0 THEN
    RAISE NOTICE '✓ Query con array @> funciona. Evaluaciones con taza 5 defectuosa: %', taza_count;
  ELSE
    RAISE WARNING '⚠ No se encontraron evaluaciones con taza 5 defectuosa';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 14: Query típica - Top muestras por puntaje
-- ============================================
\echo '[TEST 14] Probando query: Top 3 muestras por puntaje final...'

DO $$
DECLARE
  top_muestra text;
  top_puntaje int;
BEGIN
  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 = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
  ORDER BY e.puntaje_final DESC
  LIMIT 1;

  IF top_muestra IS NOT NULL THEN
    RAISE NOTICE '✓ Query top muestras funciona. Mejor muestra: % (puntaje: %)', top_muestra, top_puntaje;
  ELSE
    RAISE EXCEPTION '✗ Query top muestras falló';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 15: Función auxiliar - get_promedio_parametro_afectivo
-- ============================================
\echo '[TEST 15] Probando función: get_promedio_parametro_afectivo...'

DO $$
DECLARE
  avg_acidez numeric;
BEGIN
  SELECT get_promedio_parametro_afectivo(
    'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
    'acidez'
  ) INTO avg_acidez;

  IF avg_acidez IS NOT NULL THEN
    RAISE NOTICE '✓ Función get_promedio_parametro_afectivo funciona. Acidez promedio: %', ROUND(avg_acidez, 2);
  ELSE
    RAISE EXCEPTION '✗ Función get_promedio_parametro_afectivo falló';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 16: Función auxiliar - get_top_muestras
-- ============================================
\echo '[TEST 16] Probando función: get_top_muestras...'

DO $$
DECLARE
  resultado record;
  count_resultados int := 0;
BEGIN
  FOR resultado IN
    SELECT * FROM get_top_muestras('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 3)
  LOOP
    count_resultados := count_resultados + 1;
    RAISE NOTICE '  - %: % puntos (catador: %)', resultado.muestra_codigo, resultado.puntaje_final, resultado.catador_nombre;
  END LOOP;

  IF count_resultados > 0 THEN
    RAISE NOTICE '✓ Función get_top_muestras funciona. Resultados: %', count_resultados;
  ELSE
    RAISE EXCEPTION '✗ Función get_top_muestras no devolvió resultados';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 17: Query con índice funcional - filtrar por acidez afectiva
-- ============================================
\echo '[TEST 17] Probando query con índice funcional: acidez afectiva >= 8...'

DO $$
DECLARE
  count_acidez int;
BEGIN
  SELECT COUNT(*) INTO count_acidez
  FROM evaluacion
  WHERE ((intensidades->'acidez'->>'afectiva')::int) >= 8;

  IF count_acidez >= 0 THEN
    RAISE NOTICE '✓ Query con índice funcional funciona. Evaluaciones con acidez >= 8: %', count_acidez;
  ELSE
    RAISE EXCEPTION '✗ Query con índice funcional falló';
  END IF;
END $$;

\echo ''

-- ============================================
-- TEST 18: Validar datos de prueba cargados
-- ============================================
\echo '[TEST 18] Validando que los datos de prueba se cargaron correctamente...'

DO $$
DECLARE
  count_users int;
  count_sesiones int;
  count_muestras int;
  count_evaluaciones int;
BEGIN
  SELECT COUNT(*) INTO count_users FROM auth.users;
  SELECT COUNT(*) INTO count_sesiones FROM sesion;
  SELECT COUNT(*) INTO count_muestras FROM muestra;
  SELECT COUNT(*) INTO count_evaluaciones FROM evaluacion;

  IF count_users >= 3 AND count_sesiones >= 1 AND count_muestras >= 3 AND count_evaluaciones >= 5 THEN
    RAISE NOTICE '✓ Datos de prueba cargados:';
    RAISE NOTICE '  - Usuarios: %', count_users;
    RAISE NOTICE '  - Sesiones: %', count_sesiones;
    RAISE NOTICE '  - Muestras: %', count_muestras;
    RAISE NOTICE '  - Evaluaciones: %', count_evaluaciones;
  ELSE
    RAISE WARNING '⚠ Algunos datos de prueba pueden faltar:';
    RAISE WARNING '  - Usuarios: % (esperado: >= 3)', count_users;
    RAISE WARNING '  - Sesiones: % (esperado: >= 1)', count_sesiones;
    RAISE WARNING '  - Muestras: % (esperado: >= 3)', count_muestras;
    RAISE WARNING '  - Evaluaciones: % (esperado: >= 5)', count_evaluaciones;
  END IF;
END $$;

\echo ''
\echo '=========================================='
\echo 'Tests completados'
\echo '=========================================='
\echo ''
\echo 'Ejecuta queries de ejemplo con:'
\echo '  \i postgres/tests/example_queries.sql'
\echo ''
