create or replace function ems.fn_negative_price_predictions(p_site_id int) returns jsonb language sql stable as $fn$ with hist as ( select count(distinct (mip.interval_start at time zone 'Europe/Prague')::date)::int as ndays from ems.market_interval_price mip where mip.market_source in ('OTE_CZ', 'OTE_CZ_DAM') and mip.interval_start >= now() - interval '400 days' ), rows as ( select p.predicted_date, p.window_start_hour, p.window_end_hour, p.probability_pct, p.expected_min_price, p.reason from ems.predicted_negative_price_window p where p.site_id = p_site_id and p.predicted_date > ( current_timestamp at time zone coalesce( nullif(trim((select s.timezone from ems.site s where s.id = p_site_id)), ''), 'Europe/Prague' ) )::date and p.predicted_date <= ( current_timestamp at time zone coalesce( nullif(trim((select s.timezone from ems.site s where s.id = p_site_id)), ''), 'Europe/Prague' ) )::date + 7 order by p.predicted_date, p.window_start_hour ) select jsonb_build_object( 'predictions', coalesce( ( select jsonb_agg( jsonb_build_object( 'predicted_date', r.predicted_date, 'window_start_hour', r.window_start_hour, 'window_end_hour', r.window_end_hour, 'probability_pct', r.probability_pct, 'expected_min_price', r.expected_min_price, 'reason', coalesce(r.reason, '') ) ) from rows r ), '[]'::jsonb ), 'insufficient_history', (select ndays < 28 from hist) ); $fn$; comment on function ems.fn_negative_price_predictions(int) is 'Predikovaná okna záporných cen + flag nedostatečné historie OTE.';