create or replace function ems.fn_site_full_status(p_site_id int)
returns jsonb
language sql
stable
as $fn$
  select
    case
      when not exists (select 1 from ems.site s0 where s0.id = p_site_id) then
        jsonb_build_object('error', 'not_found')
      else jsonb_build_object(
        'site',
        (
          select jsonb_build_object(
            'id', s.id,
            'code', s.code,
            'name', s.name,
            'timezone', s.timezone
          )
          from ems.site s
          where s.id = p_site_id
        ),
        'operating_mode',
        (
          select jsonb_build_object(
            'mode_code', m.mode_code,
            'mode_name', d.name,
            'activated_at', m.activated_at,
            'activated_by', m.activated_by
          )
          from ems.site_operating_mode m
          join ems.operating_mode_def d on d.code = m.mode_code
          where m.site_id = p_site_id
        ),
        'heartbeat',
        (
          select jsonb_build_object(
            'last_seen', hb.last_seen,
            'status', hb.status
          )
          from ems.site_heartbeat hb
          where hb.site_id = p_site_id
        ),
        'inverter_latest',
        (
          select to_jsonb(li.*)
          from ems.vw_latest_inverter li
          where li.site_id = p_site_id
          order by li.measured_at desc nulls last
          limit 1
        ),
        'ev_chargers',
        coalesce(
          (
            select jsonb_agg(
              jsonb_build_object(
                'code', v.code,
                'status', v.status,
                'power_w', v.power_w,
                'measured_at', v.measured_at
              )
              order by v.measured_at desc nulls last
            )
            from (
              select distinct on (evc.charger_id)
                evc.charger_code as code,
                evc.status,
                evc.power_w,
                evc.measured_at
              from ems.vw_latest_ev_charger evc
              where evc.site_id = p_site_id
              order by evc.charger_id, evc.measured_at desc nulls last
            ) v
          ),
          '[]'::jsonb
        ),
        'heat_pump_latest',
        (
          select jsonb_build_object(
            'power_w', hp.power_w,
            'tuv_tank_temp_c', hp.tuv_tank_temp_c,
            'measured_at', hp.measured_at
          )
          from ems.vw_latest_heat_pump hp
          where hp.site_id = p_site_id
          order by hp.measured_at desc nulls last
          limit 1
        ),
        'battery_limits',
        (
          select jsonb_build_object(
            'reserve_soc', min(ab.reserve_soc_percent)::float,
            'min_soc', min(ab.min_soc_percent)::float
          )
          from ems.asset_battery ab
          where ab.site_id = p_site_id
        ),
        'active_plan',
        (
          select jsonb_build_object(
            'id', pr.id,
            'created_at', pr.created_at
          )
          from ems.planning_run pr
          where pr.site_id = p_site_id
            and pr.status = 'active'
          order by pr.created_at desc
          limit 1
        ),
        'planning_intervals',
        coalesce(
          (
            select jsonb_agg(
              jsonb_build_object(
                'interval_start', pi.interval_start,
                'battery_setpoint_w', pi.battery_setpoint_w,
                'load_baseline_w', pi.load_baseline_w,
                'pv_a_forecast_raw_w', pi.pv_a_forecast_raw_w,
                'pv_b_forecast_raw_w', pi.pv_b_forecast_raw_w,
                'pv_a_forecast_solver_w', pi.pv_a_forecast_solver_w,
                'pv_b_forecast_solver_w', pi.pv_b_forecast_solver_w
              )
              order by pi.interval_start
            )
            from ems.planning_interval pi
            where pi.run_id = (
              select pr2.id
              from ems.planning_run pr2
              where pr2.site_id = p_site_id
                and pr2.status = 'active'
              order by pr2.created_at desc
              limit 1
            )
          ),
          '[]'::jsonb
        ),
        'tomorrow_price_slot_count',
        (
          select count(*)::int
          from ems.vw_site_effective_price vep
          where vep.site_id = p_site_id
            and (vep.interval_start at time zone coalesce(
              nullif(trim((select s2.timezone from ems.site s2 where s2.id = p_site_id)), ''),
              'Europe/Prague'
            ))::date = (
              (
                current_timestamp at time zone coalesce(
                  nullif(trim((select s3.timezone from ems.site s3 where s3.id = p_site_id)), ''),
                  'Europe/Prague'
                )
              )::date + 1
            )
        )
      )
    end;
$fn$;

comment on function ems.fn_site_full_status(int) is
  'Raw data pro GET /status/full (věk telemetrie a alerty dopočítá Python).';
