-- =============================================================================
-- F6.2 (wiring) — tenants NOVOS nascem com todos os triggers de negócio
--
-- ⚠️ APLICAR COMO supabase_admin.
--
-- Até aqui os 9 schemas existentes ganharam os triggers via backfills (Lotes
-- A/B/C). Um tenant NOVO (clone_tenant_template) só ganhava channel-routing +
-- RLS. Este wiring:
--   1. attach_agnostic_triggers → SELF-CONTAINED (dirigido por colunas, não lê
--      public; sobrevive ao DROP da F6.3).
--   2. trigger AFTER INSERT em tenant_schemas dispara os 3 attach (agnostic +
--      schema_aware + notif) pro schema novo — clone_tenant_template não precisa
--      ser tocado (ele insere em tenant_schemas).
--   3. provision_account_tenant: clone ANTES do seed (seed é no-op se o schema
--      não existe; precisa do schema criado primeiro).
-- =============================================================================

BEGIN;

-- 1) attach_agnostic_triggers self-contained ---------------------------------
CREATE OR REPLACE FUNCTION public.attach_agnostic_triggers(p_schema text)
RETURNS int LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public','pg_temp'
AS $$
DECLARE r record; v_count int := 0;
BEGIN
    IF p_schema NOT LIKE 'tenant\_%' THEN RAISE EXCEPTION 'schema inválido %', p_schema; END IF;
    -- set_updated_at em toda tabela do schema que tem coluna updated_at
    FOR r IN
        SELECT c.relname AS tab
        FROM pg_class c JOIN pg_attribute a ON a.attrelid = c.oid
        WHERE c.relnamespace = p_schema::regnamespace AND c.relkind = 'r'
          AND a.attname = 'updated_at' AND NOT a.attisdropped AND c.relname NOT LIKE '\_%'
    LOOP
        EXECUTE format('DROP TRIGGER IF EXISTS set_updated_at ON %I.%I', p_schema, r.tab);
        EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %I.%I FOR EACH ROW EXECUTE FUNCTION public.set_updated_at()', p_schema, r.tab);
        v_count := v_count + 1;
    END LOOP;
    -- prevent_* em patient_groups
    IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = p_schema AND table_name = 'patient_groups') THEN
        EXECUTE format('DROP TRIGGER IF EXISTS prevent_promoting_to_system ON %I.patient_groups', p_schema);
        EXECUTE format('CREATE TRIGGER prevent_promoting_to_system BEFORE UPDATE ON %I.patient_groups FOR EACH ROW EXECUTE FUNCTION public.prevent_promoting_to_system()', p_schema);
        EXECUTE format('DROP TRIGGER IF EXISTS prevent_system_group_changes ON %I.patient_groups', p_schema);
        EXECUTE format('CREATE TRIGGER prevent_system_group_changes BEFORE UPDATE OR DELETE ON %I.patient_groups FOR EACH ROW EXECUTE FUNCTION public.prevent_system_group_changes()', p_schema);
        v_count := v_count + 2;
    END IF;
    RETURN v_count;
END $$;

-- 2) trigger de wiring em tenant_schemas -------------------------------------
GRANT EXECUTE ON FUNCTION public.attach_agnostic_triggers(text) TO postgres, service_role;
GRANT EXECUTE ON FUNCTION public.attach_schema_aware_triggers(text) TO postgres, service_role;
GRANT EXECUTE ON FUNCTION public.attach_notif_triggers(text) TO postgres, service_role;

CREATE OR REPLACE FUNCTION public.trg_attach_business_triggers()
RETURNS trigger LANGUAGE plpgsql SECURITY DEFINER SET search_path TO 'public','pg_temp'
AS $$
BEGIN
    PERFORM public.attach_agnostic_triggers(NEW.schema_name);
    PERFORM public.attach_schema_aware_triggers(NEW.schema_name);
    PERFORM public.attach_notif_triggers(NEW.schema_name);
    RETURN NULL;
END $$;
ALTER FUNCTION public.trg_attach_business_triggers() OWNER TO supabase_admin;

DROP TRIGGER IF EXISTS trg_tenant_schemas_attach ON public.tenant_schemas;
CREATE TRIGGER trg_tenant_schemas_attach
    AFTER INSERT ON public.tenant_schemas
    FOR EACH ROW EXECUTE FUNCTION public.trg_attach_business_triggers();

-- 3) provision_account_tenant: clone ANTES do seed ---------------------------
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 $$
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;

    -- F6 wiring: clone PRIMEIRO (cria o schema), seed DEPOIS (escreve no schema)
    PERFORM public.clone_tenant_template(v_tenant_id);
    PERFORM public.seed_determined_commitments(v_tenant_id);

    RETURN v_tenant_id;
END $$;

COMMIT;
