// src/db/partitions.ts
import type { PoolClient } from "pg";

const STEP = 1_000_000;

// Таблицы с RANGE (height). Хэш-партиции (core.events) не трогаем.
const RANGE_TABLES: Array<{ schema: string; table: string }> = [
    { schema: "core", table: "blocks" },
    { schema: "core", table: "validator_set" },
    { schema: "core", table: "validator_missed_blocks" },
    { schema: "core", table: "transactions" },
    { schema: "core", table: "messages" },
    { schema: "bank", table: "transfers" },
    { schema: "bank", table: "balance_deltas" },
    { schema: "stake", table: "delegation_events" },
    { schema: "stake", table: "distribution_events" },
    { schema: "gov", table: "deposits" },
    { schema: "gov", table: "votes" },
    { schema: "wasm", table: "contract_migrations" },
    { schema: "wasm", table: "executions" },
    { schema: "wasm", table: "events" },
    { schema: "wasm", table: "state_kv" },
    { schema: "tokens", table: "cw20_transfers" },
    { schema: "authz_feegrant", table: "authz_grants" },
    { schema: "authz_feegrant", table: "fee_grants" },
    { schema: "core", table: "network_params" },
];

export async function ensureCorePartitions(client: PoolClient, minH: number, maxH?: number) {
    if (!Number.isFinite(minH)) return;
    const startBase = Math.floor(minH / STEP) * STEP;
    const endBase   = Math.floor((maxH ?? minH) / STEP) * STEP;

    // один advisory-lock на создание партиций (чтобы не гонялись параллельные потоки)
    await client.query(`SELECT pg_advisory_lock($1)`, [0x70617274]); // "part"
    try {
        for (let base = startBase; base <= endBase; base += STEP) {
            const from = base;
            const to   = base + STEP;

            // blocks — сначала
            await createRangePartition(client, "core", "blocks", from, to);

            // остальные
            for (const { schema, table } of RANGE_TABLES) {
                if (schema === "core" && table === "blocks") continue;
                await createRangePartition(client, schema, table, from, to);
            }
        }
    } finally {
        await client.query(`SELECT pg_advisory_unlock($1)`, [0x70617274]);
    }
}

async function createRangePartition(
    client: PoolClient,
    schema: string,
    table: string,
    from: number,
    to: number
) {
    const parent = `"${schema}"."${table}"`;
    const child  = `"${schema}"."${table}_p${from}"`;

    // Простое и рабочее: IF NOT EXISTS + явно заданные границы.
    const sql = `
    CREATE TABLE IF NOT EXISTS ${child}
    PARTITION OF ${parent}
    FOR VALUES FROM (${from}) TO (${to});
  `;
    await client.query(sql);
}