-- ============================================
-- rioCata - Funciones y Triggers
-- ============================================

-- ============================================
-- FUNCIÓN: Actualizar updated_at
-- ============================================
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
  NEW.updated_at := clock_timestamp();
  RETURN NEW;
END $$;

COMMENT ON FUNCTION set_updated_at() IS 'Actualiza automáticamente el campo updated_at al timestamp actual';

-- Trigger para actualizar updated_at en evaluacion
CREATE TRIGGER trg_eval_updated_at
BEFORE UPDATE ON evaluacion
FOR EACH ROW EXECUTE FUNCTION set_updated_at();

-- ============================================
-- FUNCIÓN: Calcular puntaje final
-- ============================================
-- Calcula el puntaje_final sumando SOLO los valores afectivos presentes
CREATE OR REPLACE FUNCTION eval_compute_score()
RETURNS trigger LANGUAGE plpgsql AS $$
DECLARE
  s int := 0;
BEGIN
  -- Suma todos los valores afectivos presentes en intensidades
  -- Si alguno es null, COALESCE lo convierte en 0
  s := s + COALESCE((NEW.intensidades->'fragancia'      ->>'afectiva')::int, 0);
  s := s + COALESCE((NEW.intensidades->'aroma'          ->>'afectiva')::int, 0);
  s := s + COALESCE((NEW.intensidades->'sabor'          ->>'afectiva')::int, 0);
  s := s + COALESCE((NEW.intensidades->'saborResidual'  ->>'afectiva')::int, 0);
  s := s + COALESCE((NEW.intensidades->'acidez'         ->>'afectiva')::int, 0);
  s := s + COALESCE((NEW.intensidades->'dulzor'         ->>'afectiva')::int, 0);
  s := s + COALESCE((NEW.intensidades->'sensacionBoca'  ->>'afectiva')::int, 0);
  s := s + COALESCE((NEW.intensidades->'impresionGlobal'->>'afectiva')::int, 0);

  NEW.puntaje_final := s;
  RETURN NEW;
END $$;

COMMENT ON FUNCTION eval_compute_score() IS 'Calcula automáticamente el puntaje_final como suma de valores afectivos';

-- Trigger para calcular puntaje_final en INSERT y UPDATE
CREATE TRIGGER trg_eval_score_bi
BEFORE INSERT OR UPDATE OF intensidades
ON evaluacion
FOR EACH ROW EXECUTE FUNCTION eval_compute_score();

-- ============================================
-- FUNCIONES AUXILIARES DE CONSULTA
-- ============================================

-- Función para obtener el promedio de un parámetro afectivo en una sesión
CREATE OR REPLACE FUNCTION get_promedio_parametro_afectivo(
  p_sesion_id uuid,
  p_parametro text  -- 'fragancia', 'aroma', 'sabor', etc.
)
RETURNS numeric AS $$
BEGIN
  RETURN (
    SELECT AVG(((e.intensidades -> p_parametro ->>'afectiva')::int))
    FROM sesion s
    JOIN muestra m ON m.sesion_id = s.id
    JOIN evaluacion e ON e.muestra_id = m.id
    WHERE s.id = p_sesion_id
  );
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION get_promedio_parametro_afectivo(uuid, text) IS 'Obtiene el promedio de un parámetro afectivo para una sesión';

-- Función para obtener las top N muestras de una sesión por puntaje
CREATE OR REPLACE FUNCTION get_top_muestras(
  p_sesion_id uuid,
  p_limit int DEFAULT 3
)
RETURNS TABLE (
  muestra_codigo text,
  puntaje_final int,
  catador_email text,
  catador_nombre text
) AS $$
BEGIN
  RETURN QUERY
  SELECT
    m.codigo,
    e.puntaje_final,
    u.email,
    u.nombre
  FROM muestra m
  JOIN evaluacion e ON e.muestra_id = m.id
  JOIN sesion_participante sp ON sp.id = e.sesion_participante_id
  JOIN auth.users u ON u.id = sp.catador_id
  WHERE m.sesion_id = p_sesion_id
  ORDER BY e.puntaje_final DESC
  LIMIT p_limit;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION get_top_muestras(uuid, int) IS 'Obtiene las muestras con mejor puntaje de una sesión';
