-- ** TITULO      : Crear función de postgres func_working_hours_with_holidays.
-- ** OBJETIVO    : Crear la función que permita calcular el número de horas laborales en un intervalo de fechas teniendo en cuenta los días hábiles.
--					Se tiene en cuenta la hora inicial  y la hora final de trabajo.
-- ** DESCRIPCION :
--                  Se elimina la función func_working_hours_with_holidays si existe.
--					Se crea la función func_working_hours_with_holidays.


DROP FUNCTION IF EXISTS func_working_hours_with_holidays;

CREATE OR REPLACE FUNCTION func_working_hours_with_holidays(
	fechaInicial TIMESTAMP without time zone,
	fechaFinal TIMESTAMP without time zone,
	tipo_dias_excluidos integer default 0,
	OUT numHoras FLOAT8
)
AS $$
DECLARE
	diaInicial DATE := fechaInicial::date;
	diaFinal DATE := fechaFinal::date;
	horaDiaInicial FLOAT8 :=0;
	horaDiaFinal FLOAT8 :=0;
	horaInferior FLOAT8 := (SELECT value::float8 from parameters_admin where key = 'hora_inicio_laboral');
	horaSuperior FLOAT8 := (SELECT value::float8 from parameters_admin where key = 'hora_fin_laboral');
	num_horas_entre_dias FLOAT8 := 0;
	num_horas_no_laborales_di FLOAT8 := 0;
	num_horas_no_laborales_df FLOAT8 := 0;
	n_horas_laborales_TOTALES_mismo_dia FLOAT8 := 0;
	num_horas_festivas_entre_dias FLOAT8 := 0;
	iterator_day DATE := diaInicial;
	n_horas_totales FLOAT8 := 0;

BEGIN
	horaDiaInicial := EXTRACT(EPOCH FROM (fechaInicial - diaInicial ))/3600;-- AS horas_valida;
	horaDiaFinal := EXTRACT(EPOCH FROM (fechaFinal - diaFinal ))/3600;-- AS horas_valida;

	IF diaInicial = diaFinal	THEN

		IF func_holidays(diaInicial, tipo_dias_excluidos) = false THEN

				n_horas_laborales_TOTALES_mismo_dia :=	CASE
															WHEN horaDiaInicial >= horaSuperior
																THEN	0
															WHEN horaDiaInicial < horaSuperior
																AND horaDiaInicial >= horaInferior
																AND horaDiaFinal < horaSuperior
																	THEN horaDiaFinal - horaDiaInicial
															WHEN horaDiaInicial < horaSuperior
																AND horaDiaInicial >= horaInferior
																AND horaDiaFinal >= horaSuperior
																	THEN horaSuperior - horaDiaInicial
															WHEN  horaDiaInicial < horaInferior
																AND horaDiaFinal >= horaSuperior
																	THEN horaSuperior - horaInferior
															WHEN  horaDiaInicial < horaInferior
																AND horaDiaFinal < horaSuperior
																AND horaDiaFinal >= horaInferior
																	THEN horaDiaFinal - horaInferior
															WHEN horaDiaInicial < horaInferior
																AND horaDiaFinal < horaInferior
																	THEN 0
													END AS n_horas_laborales_TOTALES_mismo_dia;

				numHoras := n_horas_laborales_TOTALES_mismo_dia;

		ELSE

			numHoras := 0;

		END IF;

	ELSE

			n_horas_totales := EXTRACT(EPOCH FROM (fechaFinal - fechaInicial))/3600 AS n_horas_totales;

			num_horas_entre_dias :=		CASE WHEN diaFinal - diaInicial -1 < 0
											THEN 0
											ELSE diaFinal - diaInicial -1
										END * (24- (horaSuperior - horaInferior)) AS num_horas_no_laborales_entre_dias;

			IF num_horas_entre_dias > 0	THEN

				LOOP
					EXIT WHEN iterator_day = (diaFinal -1) ;

					iterator_day := iterator_day + 1 ;

					IF func_holidays(iterator_day, tipo_dias_excluidos) = true THEN

						num_horas_festivas_entre_dias := num_horas_festivas_entre_dias + (horaSuperior - horaInferior);

					END IF;

				END LOOP ;

			END IF;

			IF func_holidays(diaInicial, tipo_dias_excluidos) = true THEN

				num_horas_no_laborales_di := 24 - horaDiaInicial;

			ELSE

				num_horas_no_laborales_di :=   CASE
													WHEN horaDiaInicial >= horaSuperior
														THEN  24 -  horaDiaInicial
													WHEN horaDiaInicial >= horaInferior	AND (horaDiaInicial <= horaSuperior)
														THEN 24 - horaSuperior
													WHEN horaDiaInicial < horaInferior
														THEN 24 - horaSuperior + horaInferior - horaDiaInicial
												END AS num_horas_no_laborales_di;

			END IF;

			IF func_holidays(diaFinal, tipo_dias_excluidos) = true THEN

				num_horas_no_laborales_df := horaDiaFinal;

			ELSE

				num_horas_no_laborales_df :=   CASE
													WHEN horaDiaFinal >= horaSuperior
														THEN horaDiaFinal - horaSuperior + horaInferior
													WHEN horaDiaFinal >= horaInferior AND horaDiaFinal < horaSuperior
														THEN horaInferior
													WHEN  horaDiaFinal  < horaInferior
														THEN horaDiaFinal
											END  AS num_horas_no_laborales_df;

			END IF;

			numHoras := ROUND((n_horas_totales - num_horas_festivas_entre_dias - num_horas_entre_dias - num_horas_no_laborales_di - num_horas_no_laborales_df)::NUMERIC, 4);

		END IF;




END; $$
LANGUAGE plpgsql;