-- =============================================================================
-- F2 — Schema-per-tenant: provisionamento cria o schema físico
--
-- Os 3 pontos de criação de tenant passam a chamar clone_tenant_template()
-- logo após inserir em tenants/tenant_members. Tudo na mesma transação:
-- se o clone falhar, o tenant não nasce (atomicidade).
--
-- Pontos cobertos (F0 §levantamento — não há outros INSERT INTO tenants):
--   * provision_account_tenant  — wizard de cadastro (therapist/clinic_*)
--   * create_clinic_tenant      — criação avulsa de clínica
--   * ensure_personal_tenant_for_user — tenant pessoal (kind='saas'),
--     chamado também pelo trigger de signup (handle_new_user_create_personal_tenant)
--
-- Decisão Q2: TODO tenant ganha schema, inclusive therapist e pessoal.
-- Clones nascem sem triggers de negócio (F6) e fora do PostgREST (F5).
-- =============================================================================

BEGIN;

CREATE OR REPLACE FUNCTION public.create_clinic_tenant(p_name text)
 RETURNS uuid
 LANGUAGE plpgsql
 SECURITY DEFINER
AS $function$
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());

  -- F2: schema físico do tenant (rollback junto se algo falhar)
  perform public.clone_tenant_template(v_tenant);

  return v_tenant;
end;
$function$;

CREATE OR REPLACE FUNCTION public.ensure_personal_tenant_for_user(p_user_id uuid)
 RETURNS uuid
 LANGUAGE plpgsql
 SECURITY DEFINER
AS $function$
declare
  v_uid uuid;
  v_existing uuid;
  v_tenant uuid;
  v_email text;
  v_name text;
begin
  v_uid := p_user_id;
  if v_uid is null then
    raise exception 'Missing user id';
  end if;

  -- só considera tenant pessoal (kind='saas')
  select tm.tenant_id
    into v_existing
  from public.tenant_members tm
  join public.tenants t on t.id = tm.tenant_id
  where tm.user_id = v_uid
    and tm.status = 'active'
    and t.kind = 'saas'
  order by tm.created_at desc
  limit 1;

  if v_existing is not null then
    return v_existing;
  end if;

  select email into v_email
  from auth.users
  where id = v_uid;

  v_name := coalesce(split_part(v_email, '@', 1), 'Conta');

  insert into public.tenants (name, kind, created_at)
  values (v_name || ' (Pessoal)', 'saas', 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());

  -- F2: schema físico do tenant (rollback junto se algo falhar)
  perform public.clone_tenant_template(v_tenant);

  return v_tenant;
end;
$function$;

CREATE OR REPLACE FUNCTION public.provision_account_tenant(p_user_id uuid, p_kind text, p_name text DEFAULT NULL::text)
 RETURNS uuid
 LANGUAGE plpgsql
 SECURITY DEFINER
AS $function$
DECLARE
  v_tenant_id    uuid;
  v_account_type text;
  v_name         text;
BEGIN
  IF p_kind NOT IN ('therapist', 'clinic_coworking', 'clinic_reception', 'clinic_full') THEN
    RAISE EXCEPTION 'kind inválido: "%". Use: therapist, clinic_coworking, clinic_reception, clinic_full.', p_kind
      USING ERRCODE = 'P0001';
  END IF;

  v_account_type := CASE WHEN p_kind = 'therapist' THEN 'therapist' ELSE 'clinic' END;

  IF EXISTS (
    SELECT 1
    FROM public.tenant_members tm
    JOIN public.tenants t ON t.id = tm.tenant_id
    WHERE tm.user_id = p_user_id
      AND tm.role = 'tenant_admin'
      AND tm.status = 'active'
      AND t.kind = p_kind
  ) THEN
    RAISE EXCEPTION 'Usuário já possui um tenant do tipo "%".', p_kind
      USING ERRCODE = 'P0001';
  END IF;

  v_name := COALESCE(
    NULLIF(TRIM(p_name), ''),
    (
      SELECT COALESCE(NULLIF(TRIM(pr.full_name), ''), SPLIT_PART(au.email, '@', 1))
      FROM public.profiles pr
      JOIN auth.users au ON au.id = pr.id
      WHERE pr.id = p_user_id
    ),
    'Conta'
  );

  INSERT INTO public.tenants (name, kind, created_at)
  VALUES (v_name, p_kind, now())
  RETURNING id INTO v_tenant_id;

  INSERT INTO public.tenant_members (tenant_id, user_id, role, status, created_at)
  VALUES (v_tenant_id, p_user_id, 'tenant_admin', 'active', now());

  UPDATE public.profiles
  SET account_type = v_account_type
  WHERE id = p_user_id;

  PERFORM public.seed_determined_commitments(v_tenant_id);

  -- F2: schema físico do tenant (rollback junto se algo falhar)
  PERFORM public.clone_tenant_template(v_tenant_id);

  RETURN v_tenant_id;
END;
$function$;

COMMIT;
