begin;

create or replace function public.model_version_config_hash(p_version_id uuid)
returns text language sql stable security definer set search_path=''
as $$
  select encode(public.digest(convert_to(jsonb_build_object(
    'versionId',v.id,
    'configId',v.config_id,
    'version',v.version,
    'providerId',v.provider_id,
    'label',v.label,
    'description',v.description,
    'providerModel',v.provider_model,
    'modelTier',v.model_tier,
    'creditCost',v.credit_cost,
    'contextWindow',v.context_window,
    'inputCost',v.input_cost_microusd_per_million,
    'outputCost',v.output_cost_microusd_per_million,
    'enabled',v.enabled,
    'isDefault',v.is_default,
    'fallbackModelId',v.fallback_model_id,
    'settings',v.settings,
    'providerCode',p.code,
    'providerType',p.provider_type,
    'providerBaseUrl',p.base_url,
    'providerCredentialHash',case when p.encrypted_api_key is null then null else encode(public.digest(convert_to(p.encrypted_api_key,'utf8'),'sha256'),'hex') end
  )::text,'utf8'),'sha256'),'hex')
  from public.model_config_versions v
  join public.model_providers p on p.id=v.provider_id
  where v.id=p_version_id
$$;

create or replace function public.prevent_published_model_provider_runtime_mutation()
returns trigger language plpgsql set search_path=''
as $$
declare v_has_historical_version boolean;
begin
  select exists(
    select 1 from public.model_config_versions
    where provider_id=old.id and status in ('published','retired')
  ) into v_has_historical_version;

  if v_has_historical_version
    and (new.code,new.provider_type,new.base_url)
        is distinct from
        (old.code,old.provider_type,old.base_url)
  then
    raise exception 'model_provider_runtime_immutable' using
      errcode='23514',
      hint='Create a new provider and model config version, then test and publish it.';
  end if;

  if v_has_historical_version and old.enabled and not new.enabled then
    new.updated_at:=clock_timestamp();
  end if;

  if v_has_historical_version and not old.enabled and new.enabled
    and (
      new.encrypted_api_key is distinct from old.encrypted_api_key
      or not exists(
        select 1
        from public.model_config_versions v
        join public.model_connection_test_evidence e
          on e.version_id=v.id
         and e.provider_id=old.id
         and e.config_hash=public.model_version_config_hash(v.id)
         and e.http_status between 200 and 299
         and e.expires_at>clock_timestamp()
         and e.tested_at>old.updated_at
        where v.provider_id=old.id
          and v.status in ('published','retired')
      )
    )
  then
    raise exception 'model_provider_reenable_test_required' using
      errcode='23514',
      hint='Test a published or retired model version with the saved provider credentials after disabling the provider and before re-enabling it.';
  end if;

  return new;
end $$;

commit;
