-- =============================================================================
-- AgenciaPsi — Functions — Compromissos, Suporte, SaaS
-- =============================================================================
-- seed_determined_commitments, delete_commitment_full,
-- delete_determined_commitment, guard_locked_commitment,
-- create_support_session, revoke_support_session, validate_support_session,
-- saas_votar_doc, faq_votar, notice_track_click/view,
-- sanitize_phone_br, create_clinic_tenant
-- =============================================================================

CREATE FUNCTION public.create_clinic_tenant(p_name text) RETURNS uuid
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
declare
  v_uid uuid;
  v_tenant uuid;
  v_name text;
begin
  v_uid := auth.uid();
  if v_uid is null then
    raise exception 'Not authenticated';
  end if;

  v_name := nullif(trim(coalesce(p_name, '')), '');
  if v_name is null then
    v_name := 'Clínica';
  end if;

  insert into public.tenants (name, kind, created_at)
  values (v_name, 'clinic', now())
  returning id into v_tenant;

  insert into public.tenant_members (tenant_id, user_id, role, status, created_at)
  values (v_tenant, v_uid, 'tenant_admin', 'active', now());

  return v_tenant;
end;
$$;


ALTER FUNCTION public.create_clinic_tenant(p_name text) OWNER TO supabase_admin;

--
-- Name: financial_records; Type: TABLE; Schema: public; Owner: supabase_admin
--

CREATE TABLE public.financial_records (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    owner_id uuid NOT NULL,
    tenant_id uuid,
    type public.financial_record_type DEFAULT 'receita'::public.financial_record_type NOT NULL,
    amount numeric(10,2) NOT NULL,
    description text,
    category text,
    payment_method text,
    paid_at timestamp with time zone,
    due_date date,
    installments smallint DEFAULT 1,
    installment_number smallint DEFAULT 1,
    installment_group uuid,
    agenda_evento_id uuid,
    patient_id uuid,
    clinic_fee_pct numeric(5,2) DEFAULT 0,
    clinic_fee_amount numeric(10,2) DEFAULT 0,
    net_amount numeric(10,2) GENERATED ALWAYS AS ((amount - clinic_fee_amount)) STORED,
    insurance_plan_id uuid,
    notes text,
    tags text[],
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    deleted_at timestamp with time zone,
    discount_amount numeric(10,2) DEFAULT 0 NOT NULL,
    final_amount numeric(10,2) DEFAULT 0 NOT NULL,
    status text DEFAULT 'pending'::text NOT NULL,
    category_id uuid,
    CONSTRAINT financial_records_amount_check CHECK ((amount >= (0)::numeric)),
    CONSTRAINT financial_records_clinic_fee_amount_check CHECK ((clinic_fee_amount >= (0)::numeric)),
    CONSTRAINT financial_records_clinic_fee_pct_check CHECK (((clinic_fee_pct >= (0)::numeric) AND (clinic_fee_pct <= (100)::numeric))),
    CONSTRAINT financial_records_discount_amount_check CHECK ((discount_amount >= (0)::numeric)),
    CONSTRAINT financial_records_final_amount_check CHECK ((final_amount >= (0)::numeric)),
    CONSTRAINT financial_records_installments_check CHECK ((installments >= 1)),
    CONSTRAINT financial_records_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'paid'::text, 'partial'::text, 'overdue'::text, 'cancelled'::text, 'refunded'::text])))
);


ALTER TABLE public.financial_records OWNER TO supabase_admin;

--
-- Name: create_financial_record_for_session(uuid, uuid, uuid, uuid, numeric, date); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.create_financial_record_for_session(p_tenant_id uuid, p_owner_id uuid, p_patient_id uuid, p_agenda_evento_id uuid, p_amount numeric, p_due_date date) RETURNS SETOF public.financial_records
CREATE FUNCTION public.create_support_session(p_tenant_id uuid, p_ttl_minutes integer DEFAULT 60) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
DECLARE
  v_admin_id  uuid;
  v_role      text;
  v_token     text;
  v_expires   timestamp with time zone;
  v_session   support_sessions;
BEGIN
  -- Verifica autenticação
  v_admin_id := auth.uid();
  IF v_admin_id IS NULL THEN
    RAISE EXCEPTION 'Não autenticado.' USING ERRCODE = 'P0001';
  END IF;

  -- Verifica role saas_admin
  SELECT role INTO v_role
    FROM public.profiles
   WHERE id = v_admin_id;

  IF v_role <> 'saas_admin' THEN
    RAISE EXCEPTION 'Acesso negado. Somente saas_admin pode criar sessões de suporte.'
      USING ERRCODE = 'P0002';
  END IF;

  -- Valida TTL (1 a 120 minutos)
  IF p_ttl_minutes < 1 OR p_ttl_minutes > 120 THEN
    RAISE EXCEPTION 'TTL inválido. Use entre 1 e 120 minutos.'
      USING ERRCODE = 'P0003';
  END IF;

  -- Valida tenant
  IF NOT EXISTS (SELECT 1 FROM public.tenants WHERE id = p_tenant_id) THEN
    RAISE EXCEPTION 'Tenant não encontrado.'
      USING ERRCODE = 'P0004';
  END IF;

  -- Gera token único (64 chars hex, sem pgcrypto)
  v_token   := replace(gen_random_uuid()::text, '-', '') || replace(gen_random_uuid()::text, '-', '');
  v_expires := now() + (p_ttl_minutes || ' minutes')::interval;

  -- Insere sessão
  INSERT INTO public.support_sessions (tenant_id, admin_id, token, expires_at)
  VALUES (p_tenant_id, v_admin_id, v_token, v_expires)
  RETURNING * INTO v_session;

  RETURN json_build_object(
    'token',      v_session.token,
    'expires_at', v_session.expires_at,
    'session_id', v_session.id
  );
END;
$$;


ALTER FUNCTION public.create_support_session(p_tenant_id uuid, p_ttl_minutes integer) OWNER TO supabase_admin;

--
-- Name: therapist_payouts; Type: TABLE; Schema: public; Owner: supabase_admin
--

CREATE TABLE public.therapist_payouts (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    owner_id uuid NOT NULL,
    tenant_id uuid NOT NULL,
    period_start date NOT NULL,
    period_end date NOT NULL,
    total_sessions integer DEFAULT 0 NOT NULL,
    gross_amount numeric(10,2) DEFAULT 0 NOT NULL,
    clinic_fee_total numeric(10,2) DEFAULT 0 NOT NULL,
    net_amount numeric(10,2) DEFAULT 0 NOT NULL,
    status text DEFAULT 'pending'::text NOT NULL,
    paid_at timestamp with time zone,
    notes text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT therapist_payouts_clinic_fee_total_check CHECK ((clinic_fee_total >= (0)::numeric)),
    CONSTRAINT therapist_payouts_gross_amount_check CHECK ((gross_amount >= (0)::numeric)),
    CONSTRAINT therapist_payouts_net_amount_check CHECK ((net_amount >= (0)::numeric)),
    CONSTRAINT therapist_payouts_period_chk CHECK ((period_end >= period_start)),
    CONSTRAINT therapist_payouts_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'paid'::text, 'cancelled'::text])))
);


ALTER TABLE public.therapist_payouts OWNER TO supabase_admin;

--
-- Name: create_therapist_payout(uuid, uuid, date, date); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.create_therapist_payout(p_tenant_id uuid, p_therapist_id uuid, p_period_start date, p_period_end date) RETURNS public.therapist_payouts
CREATE FUNCTION public.delete_commitment_full(p_tenant_id uuid, p_commitment_id uuid) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
declare
  v_is_native boolean;
  v_fields int := 0;
  v_logs int := 0;
  v_parent int := 0;
begin
  if auth.uid() is null then
    raise exception 'Not authenticated';
  end if;

  if not exists (
    select 1
    from public.tenant_members tm
    where tm.tenant_id = p_tenant_id
      and tm.user_id = auth.uid()
      and tm.status = 'active'
  ) then
    raise exception 'Not allowed';
  end if;

  select dc.is_native
    into v_is_native
  from public.determined_commitments dc
  where dc.tenant_id = p_tenant_id
    and dc.id = p_commitment_id;

  if v_is_native is null then
    raise exception 'Commitment not found';
  end if;

  if v_is_native = true then
    raise exception 'Cannot delete native commitment';
  end if;

  delete from public.determined_commitment_fields
   where tenant_id = p_tenant_id
     and commitment_id = p_commitment_id;
  get diagnostics v_fields = row_count;

  delete from public.commitment_time_logs
   where tenant_id = p_tenant_id
     and commitment_id = p_commitment_id;
  get diagnostics v_logs = row_count;

  delete from public.determined_commitments
   where tenant_id = p_tenant_id
     and id = p_commitment_id;
  get diagnostics v_parent = row_count;

  if v_parent <> 1 then
    raise exception 'Parent not deleted (RLS/owner issue).';
  end if;

  return jsonb_build_object(
    'ok', true,
    'deleted', jsonb_build_object(
      'fields', v_fields,
      'logs', v_logs,
      'commitment', v_parent
    )
  );
end;
$$;


ALTER FUNCTION public.delete_commitment_full(p_tenant_id uuid, p_commitment_id uuid) OWNER TO postgres;

--
-- Name: delete_determined_commitment(uuid, uuid); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.delete_determined_commitment(p_tenant_id uuid, p_commitment_id uuid) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
declare
  v_is_native boolean;
  v_fields_deleted int := 0;
  v_logs_deleted int := 0;
  v_commitment_deleted int := 0;
begin
  if auth.uid() is null then
    raise exception 'Not authenticated';
  end if;

  if not exists (
    select 1
    from public.tenant_members tm
    where tm.tenant_id = p_tenant_id
      and tm.user_id = auth.uid()
      and tm.status = 'active'
  ) then
    raise exception 'Not allowed';
  end if;

  select dc.is_native
    into v_is_native
  from public.determined_commitments dc
  where dc.tenant_id = p_tenant_id
    and dc.id = p_commitment_id;

  if v_is_native is null then
    raise exception 'Commitment not found for tenant';
  end if;

  if v_is_native = true then
    raise exception 'Cannot delete native commitment';
  end if;

  delete from public.determined_commitment_fields f
   where f.tenant_id = p_tenant_id
     and f.commitment_id = p_commitment_id;
  get diagnostics v_fields_deleted = row_count;

  delete from public.commitment_time_logs l
   where l.tenant_id = p_tenant_id
     and l.commitment_id = p_commitment_id;
  get diagnostics v_logs_deleted = row_count;

  delete from public.determined_commitments dc
   where dc.tenant_id = p_tenant_id
     and dc.id = p_commitment_id;
  get diagnostics v_commitment_deleted = row_count;

  if v_commitment_deleted <> 1 then
    raise exception 'Delete did not remove the commitment (tenant mismatch?)';
  end if;

  return jsonb_build_object(
    'ok', true,
    'tenant_id', p_tenant_id,
    'commitment_id', p_commitment_id,
    'deleted', jsonb_build_object(
      'fields', v_fields_deleted,
      'logs', v_logs_deleted,
      'commitment', v_commitment_deleted
    )
  );
end;
$$;


ALTER FUNCTION public.delete_determined_commitment(p_tenant_id uuid, p_commitment_id uuid) OWNER TO supabase_admin;

--
-- Name: dev_list_auth_users(integer); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.dev_list_auth_users(p_limit integer DEFAULT 50) RETURNS TABLE(id uuid, email text, created_at timestamp with time zone)
CREATE FUNCTION public.faq_votar(faq_id uuid) RETURNS void
    LANGUAGE sql SECURITY DEFINER
    AS $$
  update public.saas_faq
  set votos = votos + 1,
      updated_at = now()
  where id = faq_id
    and ativo = true;
$$;


ALTER FUNCTION public.faq_votar(faq_id uuid) OWNER TO supabase_admin;

--
-- Name: fix_all_subscription_mismatches(); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.fix_all_subscription_mismatches() RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
declare
  r record;
begin
  for r in
    select distinct s.user_id as owner_id
    from public.subscriptions s
    where s.status = 'active'
      and s.user_id is not null
  loop
    perform public.rebuild_owner_entitlements(r.owner_id);
  end loop;
end;
$$;


ALTER FUNCTION public.fix_all_subscription_mismatches() OWNER TO supabase_admin;

--
-- Name: fn_agenda_regras_semanais_no_overlap(); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.fn_agenda_regras_semanais_no_overlap() RETURNS trigger
CREATE FUNCTION public.guard_locked_commitment() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
begin
  if (old.is_locked = true) then
    if (tg_op = 'DELETE') then
      raise exception 'Compromisso bloqueado não pode ser excluído.';
    end if;

    if (tg_op = 'UPDATE') then
      if (new.active = false) then
        raise exception 'Compromisso bloqueado não pode ser desativado.';
      end if;

      -- trava renomear (mantém o "Sessão" sempre igual)
      if (new.name is distinct from old.name) then
        raise exception 'Compromisso bloqueado não pode ser renomeado.';
      end if;

      -- se quiser travar descrição também, descomente:
      -- if (new.description is distinct from old.description) then
      --   raise exception 'Compromisso bloqueado não pode alterar descrição.';
      -- end if;
    end if;
  end if;

  return new;
end;
$$;


ALTER FUNCTION public.guard_locked_commitment() OWNER TO supabase_admin;

--
-- Name: guard_no_change_core_plan_key(); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.guard_no_change_core_plan_key() RETURNS trigger
CREATE FUNCTION public.notice_track_click(p_notice_id uuid) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
begin
  update public.global_notices
  set clicks_count = clicks_count + 1
  where id = p_notice_id;
end;
$$;


ALTER FUNCTION public.notice_track_click(p_notice_id uuid) OWNER TO supabase_admin;

--
-- Name: notice_track_view(uuid); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.notice_track_view(p_notice_id uuid) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
begin
  update public.global_notices
  set views_count = views_count + 1
  where id = p_notice_id;
end;
$$;


ALTER FUNCTION public.notice_track_view(p_notice_id uuid) OWNER TO supabase_admin;

--
-- Name: notify_on_intake(); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.notify_on_intake() RETURNS trigger
CREATE FUNCTION public.revoke_support_session(p_token text) RETURNS boolean
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
DECLARE
  v_admin_id uuid;
  v_role     text;
BEGIN
  v_admin_id := auth.uid();
  IF v_admin_id IS NULL THEN
    RAISE EXCEPTION 'Não autenticado.' USING ERRCODE = 'P0001';
  END IF;

  SELECT role INTO v_role FROM public.profiles WHERE id = v_admin_id;
  IF v_role <> 'saas_admin' THEN
    RAISE EXCEPTION 'Acesso negado.' USING ERRCODE = 'P0002';
  END IF;

  DELETE FROM public.support_sessions
   WHERE token = p_token
     AND admin_id = v_admin_id;

  RETURN FOUND;
END;
$$;


ALTER FUNCTION public.revoke_support_session(p_token text) OWNER TO supabase_admin;

--
-- Name: rotate_patient_invite_token(text); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.rotate_patient_invite_token(p_new_token text) RETURNS uuid
CREATE FUNCTION public.saas_votar_doc(p_doc_id uuid, p_util boolean) RETURNS jsonb
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
declare
  v_uid         uuid := auth.uid();
  v_voto_antigo boolean;
begin
  if v_uid is null then
    raise exception 'Não autenticado';
  end if;

  -- Verifica se já votou
  select util into v_voto_antigo
  from public.saas_doc_votos
  where doc_id = p_doc_id and user_id = v_uid;

  if found then
    -- Já votou igual → cancela o voto (toggle)
    if v_voto_antigo = p_util then
      delete from public.saas_doc_votos
      where doc_id = p_doc_id and user_id = v_uid;

      update public.saas_docs set
        votos_util     = greatest(0, votos_util     - (case when p_util  then 1 else 0 end)),
        votos_nao_util = greatest(0, votos_nao_util - (case when not p_util then 1 else 0 end)),
        updated_at = now()
      where id = p_doc_id;

      return jsonb_build_object('acao', 'removido', 'util', null);
    else
      -- Mudou de voto
      update public.saas_doc_votos set util = p_util, updated_at = now()
      where doc_id = p_doc_id and user_id = v_uid;

      update public.saas_docs set
        votos_util     = greatest(0, votos_util     + (case when p_util  then 1 else -1 end)),
        votos_nao_util = greatest(0, votos_nao_util + (case when not p_util then 1 else -1 end)),
        updated_at = now()
      where id = p_doc_id;

      return jsonb_build_object('acao', 'atualizado', 'util', p_util);
    end if;
  else
    -- Primeiro voto
    insert into public.saas_doc_votos (doc_id, user_id, util)
    values (p_doc_id, v_uid, p_util);

    update public.saas_docs set
      votos_util     = votos_util     + (case when p_util  then 1 else 0 end),
      votos_nao_util = votos_nao_util + (case when not p_util then 1 else 0 end),
      updated_at = now()
    where id = p_doc_id;

    return jsonb_build_object('acao', 'registrado', 'util', p_util);
  end if;
end;
$$;


ALTER FUNCTION public.saas_votar_doc(p_doc_id uuid, p_util boolean) OWNER TO supabase_admin;

--
-- Name: safe_delete_patient(uuid); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.safe_delete_patient(p_patient_id uuid) RETURNS jsonb
CREATE FUNCTION public.sanitize_phone_br(raw_phone text) RETURNS text
    LANGUAGE plpgsql IMMUTABLE
    AS $$                                                                           DECLARE digits text;
  BEGIN
    digits := regexp_replace(COALESCE(raw_phone, ''), '[^0-9]', '', 'g');
    IF digits = '' THEN RETURN ''; END IF;
    IF length(digits) = 10 OR length(digits) = 11 THEN
      digits := '55' || digits;
    END IF;
    RETURN digits;
  END; $$;


ALTER FUNCTION public.sanitize_phone_br(raw_phone text) OWNER TO supabase_admin;

--
-- Name: seed_default_financial_categories(uuid); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.seed_default_financial_categories(p_user_id uuid) RETURNS void
CREATE FUNCTION public.seed_determined_commitments(p_tenant_id uuid) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
declare
  v_id uuid;
begin
  -- Sessão (locked + sempre ativa)
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'session'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'session', true, true, 'Sessão', 'Sessão com paciente');
  end if;

  -- Leitura
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'reading'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'reading', false, true, 'Leitura', 'Praticar leitura');
  end if;

  -- Supervisão
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'supervision'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'supervision', false, true, 'Supervisão', 'Supervisão');
  end if;

  -- Aula ✅ (corrigido)
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'class'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'class', false, false, 'Aula', 'Dar aula');
  end if;

  -- Análise pessoal
  if not exists (
    select 1 from public.determined_commitments
    where tenant_id = p_tenant_id and is_native = true and native_key = 'analysis'
  ) then
    insert into public.determined_commitments
      (tenant_id, is_native, native_key, is_locked, active, name, description)
    values
      (p_tenant_id, true, 'analysis', false, true, 'Análise Pessoal', 'Minha análise pessoal');
  end if;

  -- -------------------------------------------------------
  -- Campos padrão (idempotentes por (commitment_id, key))
  -- -------------------------------------------------------

  -- Leitura
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'reading'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'book') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'book', 'Livro', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'author') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'author', 'Autor', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;

  -- Supervisão
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'supervision'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'supervisor') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'supervisor', 'Supervisor', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'topic') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'topic', 'Assunto', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;

  -- Aula
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'class'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'theme') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'theme', 'Tema', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'group') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'group', 'Turma', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;

  -- Análise
  select id into v_id
  from public.determined_commitments
  where tenant_id = p_tenant_id and is_native = true and native_key = 'analysis'
  limit 1;

  if v_id is not null then
    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'analyst') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'analyst', 'Analista', 'text', false, 10);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'focus') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'focus', 'Foco', 'text', false, 20);
    end if;

    if not exists (select 1 from public.determined_commitment_fields where commitment_id = v_id and key = 'notes') then
      insert into public.determined_commitment_fields (tenant_id, commitment_id, key, label, field_type, required, sort_order)
      values (p_tenant_id, v_id, 'notes', 'Observação', 'textarea', false, 30);
    end if;
  end if;
end;
$$;


ALTER FUNCTION public.seed_determined_commitments(p_tenant_id uuid) OWNER TO supabase_admin;

--
-- Name: set_insurance_plans_updated_at(); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.set_insurance_plans_updated_at() RETURNS trigger
CREATE FUNCTION public.validate_support_session(p_token text) RETURNS json
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
DECLARE
  v_session support_sessions;
BEGIN
  IF p_token IS NULL OR length(trim(p_token)) < 32 THEN
    RETURN json_build_object('valid', false, 'tenant_id', null);
  END IF;

  SELECT * INTO v_session
    FROM public.support_sessions
   WHERE token = p_token
     AND expires_at > now()
   LIMIT 1;

  IF NOT FOUND THEN
    RETURN json_build_object('valid', false, 'tenant_id', null);
  END IF;

  RETURN json_build_object(
    'valid',     true,
    'tenant_id', v_session.tenant_id
  );
END;
$$;


ALTER FUNCTION public.validate_support_session(p_token text) OWNER TO supabase_admin;

--
-- Name: whoami(); Type: FUNCTION; Schema: public; Owner: supabase_admin
--

CREATE FUNCTION public.whoami() RETURNS TABLE(uid uuid, role text)
