create or replace function ems.fn_site_configuration(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 null::jsonb
      else jsonb_build_object(
        'site',
        (
          select to_jsonb(x)
          from (
            select
              s.id,
              s.code,
              s.name,
              s.timezone,
              s.latitude::float8 as latitude,
              s.longitude::float8 as longitude,
              s.active,
              s.notes,
              s.created_at
            from ems.site s
            where s.id = p_site_id
          ) x
        ),
        'grid_connection',
        (
          select to_jsonb(g.*)
          from ems.site_grid_connection g
          where g.site_id = p_site_id
          limit 1
        ),
        'market_config',
        (
          select to_jsonb(m.*)
          from ems.site_market_config m
          where m.site_id = p_site_id
            and m.valid_from <= now()
            and (m.valid_to is null or m.valid_to > now())
          order by m.valid_from desc
          limit 1
        ),
        'market_config_note',
        'Zelený bonus za výrobu je u FVE polí (asset_pv_array), ne v obchodní konfiguraci.',
        'endpoints',
        coalesce(
          (
            select jsonb_agg(
              to_jsonb(e.*)
              || jsonb_build_object(
                'auth_reference',
                case
                  when e.auth_reference is null or btrim(e.auth_reference::text) = '' then null::text
                  when length(btrim(e.auth_reference::text)) <= 4 then 'nastaveno'::text
                  else concat('…', right(btrim(e.auth_reference::text), 2))
                end
              )
              order by e.id
            )
            from ems.site_endpoint e
            where e.site_id = p_site_id
          ),
          '[]'::jsonb
        ),
        'inverters',
        coalesce(
          (
            select jsonb_agg(
              (
                (
                  to_jsonb(ai.*)
                  - 'deye_last_system_time_sync_at'::text
                  - 'deye_last_system_time_sync_minute'::text
                  - 'deye_last_tou_inactive_write_prague_date'::text
                  - 'deye_tou_inactive_signature'::text
                )
                || jsonb_build_object(
                  'endpoint_connection',
                  (
                    select ep.host || case
                      when ep.port is not null then ':' || ep.port::text
                      else ''
                    end
                    from ems.site_endpoint ep
                    where ep.id = ai.endpoint_id
                  ),
                  'deye_meta',
                  case
                    when jsonb_strip_nulls(
                      jsonb_build_object(
                        'deye_last_system_time_sync_at', to_jsonb(ai.deye_last_system_time_sync_at),
                        'deye_last_system_time_sync_minute', to_jsonb(ai.deye_last_system_time_sync_minute),
                        'deye_last_tou_inactive_write_prague_date',
                        to_jsonb(ai.deye_last_tou_inactive_write_prague_date),
                        'deye_tou_inactive_signature', to_jsonb(ai.deye_tou_inactive_signature)
                      )
                    ) = '{}'::jsonb then null::jsonb
                    else jsonb_strip_nulls(
                      jsonb_build_object(
                        'deye_last_system_time_sync_at', to_jsonb(ai.deye_last_system_time_sync_at),
                        'deye_last_system_time_sync_minute', to_jsonb(ai.deye_last_system_time_sync_minute),
                        'deye_last_tou_inactive_write_prague_date',
                        to_jsonb(ai.deye_last_tou_inactive_write_prague_date),
                        'deye_tou_inactive_signature', to_jsonb(ai.deye_tou_inactive_signature)
                      )
                    )
                  end
                )
              )
              order by ai.id
            )
            from ems.asset_inverter ai
            where ai.site_id = p_site_id
          ),
          '[]'::jsonb
        ),
        'batteries',
        coalesce(
          (
            select jsonb_agg(to_jsonb(b.*) order by b.id)
            from ems.asset_battery b
            where b.site_id = p_site_id
          ),
          '[]'::jsonb
        ),
        'pv_arrays',
        coalesce(
          (
            select jsonb_agg(to_jsonb(p.*) order by p.id)
            from ems.asset_pv_array p
            where p.site_id = p_site_id
          ),
          '[]'::jsonb
        ),
        'ev_chargers',
        coalesce(
          (
            select jsonb_agg(
              to_jsonb(ec.*)
              || jsonb_build_object(
                'endpoint_connection',
                se.host || case
                  when se.port is not null then ':' || se.port::text
                  else ''
                end
              )
              order by ec.id
            )
            from ems.asset_ev_charger ec
            left join ems.site_endpoint se on se.id = ec.endpoint_id
            where ec.site_id = p_site_id
          ),
          '[]'::jsonb
        ),
        'vehicles',
        coalesce(
          (
            select jsonb_agg(
              to_jsonb(v.*)
              || jsonb_build_object(
                'api_reference',
                case
                  when v.api_reference is null or btrim(v.api_reference::text) = '' then null::text
                  when length(btrim(v.api_reference::text)) <= 4 then 'nastaveno'::text
                  else concat('…', right(btrim(v.api_reference::text), 2))
                end
              )
              order by v.code
            )
            from ems.asset_vehicle v
            where v.site_id = p_site_id
          ),
          '[]'::jsonb
        ),
        'heat_pumps',
        coalesce(
          (
            select jsonb_agg(
              to_jsonb(hp.*)
              || jsonb_build_object(
                'endpoint_connection',
                se.host || case
                  when se.port is not null then ':' || se.port::text
                  else ''
                end
              )
              order by hp.id
            )
            from ems.asset_heat_pump hp
            left join ems.site_endpoint se on se.id = hp.endpoint_id
            where hp.site_id = p_site_id
          ),
          '[]'::jsonb
        ),
        'operating_mode',
        (
          select to_jsonb(om)
          from (
            select
              m.mode_code,
              m.activated_at,
              m.activated_by,
              m.valid_until,
              m.previous_mode,
              m.notes,
              d.name as mode_name,
              d.description as mode_description,
              d.loxone_mode_value,
              d.ev_enabled,
              d.heat_pump_enabled,
              d.battery_mode,
              d.grid_mode,
              d.is_autonomous
            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
          ) om
        ),
        'active_overrides',
        coalesce(
          (
            select jsonb_agg(to_jsonb(o.*) order by o.valid_from desc)
            from (
              select *
              from ems.site_override so
              where so.site_id = p_site_id
                and so.valid_from <= now()
                and (so.valid_to is null or so.valid_to > now())
              order by so.valid_from desc
              limit 50
            ) o
          ),
          '[]'::jsonb
        ),
        'pv_forecast_calibration',
        (
          select to_jsonb(c.*)
          from ems.site_pv_forecast_calibration c
          where c.site_id = p_site_id
        ),
        'operational',
        jsonb_build_object(
          'heartbeat_last_seen',
          (select hb.last_seen from ems.site_heartbeat hb where hb.site_id = p_site_id limit 1),
          'heartbeat_status',
          (select hb.status from ems.site_heartbeat hb where hb.site_id = p_site_id limit 1),
          'has_active_plan',
          exists (
            select 1
            from ems.planning_run pr
            where pr.site_id = p_site_id
              and pr.status = 'active'
          ),
          'active_plan_created_at',
          (
            select 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
          )
        )
      )
    end;
$fn$;

comment on function ems.fn_site_configuration(int) is
  'GET /configuration jako jeden JSON bundle (maskované reference, deye_meta).';
