-- =============================================================================
-- F6.1 — Migração de DADOS public -> schemas tenant (cutover)
--
-- ⚠️ APLICAR COMO supabase_admin (precisa SET session_replication_role=replica
--    pra desabilitar checagem de FK durante o bulk insert — postgres não pode).
--
--    docker exec -i -e PGPASSWORD=postgres supabase_db_agenciapsi-primesakai \
--      psql -U supabase_admin -h 127.0.0.1 -d postgres -v ON_ERROR_STOP=1 \
--      < database-novo/manual/f6_1_migrate_data.supabase_admin.sql
--
-- COPIA (não move) os dados de cada tenant pras suas tabelas no schema. Os
-- dados continuam em public até o DROP da F6.3. Idempotente via ON CONFLICT
-- DO NOTHING (rodar de novo não duplica).
--
--   * tabelas com tenant_id: INSERT ... SELECT WHERE tenant_id = <id>, sem a
--     coluna tenant_id (não existe no schema)
--   * 3 filhas sem tenant_id (commitment_services, insurance_plan_services,
--     recurrence_rule_services): particionadas via JOIN no pai
--   * financial_categories / therapist_payout_records: 0 linhas, ignoradas
--   * as 6 tabelas anon-facing (F1b) NÃO existem no schema → naturalmente fora
--   * reset de sequences (4 tabelas bigserial) ao final
-- =============================================================================

SET session_replication_role = replica;

DO $$
DECLARE
    t_row   record;
    tab     record;
    v_cols  text;
    v_n     bigint;
    -- filhas sem tenant_id: tabela -> (pai, fk_local, pk_pai)
    child_joins jsonb := jsonb_build_object(
        'commitment_services',      jsonb_build_object('parent','agenda_eventos','fk','commitment_id'),
        'insurance_plan_services',  jsonb_build_object('parent','insurance_plans','fk','insurance_plan_id'),
        'recurrence_rule_services', jsonb_build_object('parent','recurrence_rules','fk','rule_id')
    );
    cj jsonb;
BEGIN
    FOR t_row IN
        SELECT t.id AS tenant_id, ts.schema_name
        FROM public.tenants t
        JOIN public.tenant_schemas ts ON ts.tenant_id = t.id
        ORDER BY t.created_at, t.id
    LOOP
        FOR tab IN
            SELECT c.relname AS table_name
            FROM pg_class c
            WHERE c.relnamespace = t_row.schema_name::regnamespace
              AND c.relkind = 'r'
              AND c.relname NOT LIKE '\_%'
            ORDER BY c.relname
        LOOP
            -- pula se a tabela não existe em public (defensivo)
            IF NOT EXISTS (SELECT 1 FROM information_schema.tables
                           WHERE table_schema='public' AND table_name=tab.table_name) THEN
                CONTINUE;
            END IF;

            -- colunas presentes em AMBOS (schema e public): exclui tenant_id
            -- (some no schema), singleton (só no schema, fica no default) e
            -- colunas GENERATED (net_amount, margin_brl — não aceitam INSERT)
            SELECT string_agg(quote_ident(sc.column_name), ', ' ORDER BY sc.ordinal_position)
              INTO v_cols
              FROM information_schema.columns sc
             WHERE sc.table_schema = t_row.schema_name AND sc.table_name = tab.table_name
               AND sc.is_generated = 'NEVER'
               AND EXISTS (SELECT 1 FROM information_schema.columns pc
                           WHERE pc.table_schema='public' AND pc.table_name=tab.table_name
                             AND pc.column_name = sc.column_name
                             AND pc.is_generated = 'NEVER');

            IF v_cols IS NULL THEN CONTINUE; END IF;

            cj := child_joins -> tab.table_name;

            IF cj IS NOT NULL THEN
                -- filha sem tenant_id: particiona via JOIN no pai
                EXECUTE format(
                    'INSERT INTO %I.%I (%s) SELECT %s FROM public.%I ch '
                    || 'JOIN public.%I p ON p.id = ch.%I WHERE p.tenant_id = %L '
                    || 'ON CONFLICT DO NOTHING',
                    t_row.schema_name, tab.table_name, v_cols,
                    (SELECT string_agg('ch.'||quote_ident(x), ', ' ORDER BY ord)
                       FROM (SELECT trim(both ' ' from unnest(string_to_array(v_cols, ','))) AS x,
                                    generate_subscripts(string_to_array(v_cols, ','),1) AS ord) y),
                    tab.table_name,
                    (cj->>'parent'), (cj->>'fk'),
                    t_row.tenant_id
                );
            ELSIF EXISTS (SELECT 1 FROM information_schema.columns
                          WHERE table_schema='public' AND table_name=tab.table_name AND column_name='tenant_id') THEN
                -- tabela com tenant_id: filtro direto
                EXECUTE format(
                    'INSERT INTO %I.%I (%s) SELECT %s FROM public.%I WHERE tenant_id = %L ON CONFLICT DO NOTHING',
                    t_row.schema_name, tab.table_name, v_cols, v_cols, tab.table_name, t_row.tenant_id
                );
            ELSE
                -- sem tenant_id e não é filha mapeada (financial_categories etc.):
                -- só migra se tiver 0 dependência de tenant — pula (vazias hoje)
                CONTINUE;
            END IF;

            GET DIAGNOSTICS v_n = ROW_COUNT;
            IF v_n > 0 THEN
                RAISE NOTICE 'F6.1 %.%: % linhas', t_row.schema_name, tab.table_name, v_n;
            END IF;
        END LOOP;
    END LOOP;
END $$;

-- ---------------------------------------------------------------------------
-- Reset de sequences (tabelas bigserial) em cada schema
-- ---------------------------------------------------------------------------
DO $$
DECLARE
    t_row record;
    r record;
    v_seq text;
BEGIN
    FOR t_row IN SELECT schema_name FROM public.tenant_schemas LOOP
        FOR r IN
            SELECT c.relname AS table_name, a.attname AS column_name
            FROM pg_attrdef d
            JOIN pg_class c ON c.oid = d.adrelid
            JOIN pg_attribute a ON a.attrelid = d.adrelid AND a.attnum = d.adnum
            WHERE c.relnamespace = t_row.schema_name::regnamespace
              AND pg_get_expr(d.adbin, d.adrelid) LIKE 'nextval(%'
        LOOP
            v_seq := pg_get_serial_sequence(format('%I.%I', t_row.schema_name, r.table_name), r.column_name);
            IF v_seq IS NOT NULL THEN
                EXECUTE format('SELECT setval(%L, COALESCE((SELECT MAX(%I) FROM %I.%I), 0) + 1, false)',
                               v_seq, r.column_name, t_row.schema_name, r.table_name);
                RAISE NOTICE 'F6.1 seq %.% -> %', t_row.schema_name, r.table_name, v_seq;
            END IF;
        END LOOP;
    END LOOP;
END $$;

SET session_replication_role = origin;
