import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
/**
 * @copyright Sister Software
 * @license AGPL-3.0
 * @author Teffen Ellis, et al.
 */
import { ProgressBar } from "@inkjs/ui";
import FastGlob from "fast-glob";
import { Box, Text } from "ink";
import { takeInParallel } from "mailwoman/core";
import { formatMinutes, formatQuantity, takeAsync, tallyPatternCount } from "mailwoman/core/resources";
import { availableParallelism } from "node:os";
import { setImmediate } from "node:timers/promises";
import { PathBuilder } from "path-ts";
import { Piscina } from "piscina";
import { useCallback, useEffect, useState } from "react";
import zod from "zod";
const piscina = new Piscina({
    filename: PathBuilder.from(import.meta.dirname, "_app_worker.mjs").href,
    idleTimeout: 1000 * 10,
});
const BATCH_SIZE = availableParallelism();
const ArgumentsSchema = zod.array(zod.string().describe("Path to the Who's On First data directory"));
export { ArgumentsSchema as args };
const startTime = performance.now();
const WOFPrepare = ({ args: [wofDataAdminDirectory] }) => {
    const [insertionCount, setInsertionCount] = useState(0);
    const [throughput, setThroughput] = useState(0);
    const [recordCount, setRecordCount] = useState(-1);
    const percentage = recordCount === -1 ? 0 : (insertionCount / recordCount) * 100;
    const elapsed = performance.now() - startTime;
    const eta = Number.isFinite(throughput) ? (recordCount - insertionCount) / throughput : NaN;
    useEffect(() => {
        if (percentage < 100)
            return;
        setImmediate().then(() => {
            process.exit(0);
        });
    }, [percentage]);
    const delegateInsertion = useCallback(async (filePath) => {
        if (Date.now()) {
            await piscina.run(filePath.toString());
            return;
        }
        return fetch("http://localhost:3000/admin/wof", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({
                filePath: filePath.toString(),
            }),
        }).then(async (response) => {
            if (response.ok) {
                performance.mark("insertion");
                return;
            }
            const body = await response.json().catch(() => null);
            if (body) {
                throw new Error(`Failed to insert record: ${JSON.stringify(body)}`);
            }
            throw new Error(`Failed to insert record: ${response.statusText}`);
        });
    }, []);
    useEffect(() => {
        tallyPatternCount(["*.geojson"], wofDataAdminDirectory).then(setRecordCount);
    }, [wofDataAdminDirectory]);
    useEffect(() => {
        ;
        (async () => {
            const matchStream = FastGlob.stream(["**/*.geojson"], {
                cwd: wofDataAdminDirectory,
                absolute: true,
            });
            for await (const fileNames of takeAsync(matchStream, BATCH_SIZE)) {
                // console.log("Inserting", fileNames.length, "records")
                // const batchStartTime = performance.now()
                const batchIterator = takeInParallel(fileNames, BATCH_SIZE, delegateInsertion);
                await Array.fromAsync(batchIterator);
                // const batchEndTime = performance.now()
                // console.log(`Batch took ${batchEndTime - batchStartTime}s`)
                setInsertionCount((count) => count + fileNames.length);
            }
        })();
    }, [delegateInsertion, wofDataAdminDirectory]);
    useEffect(() => {
        const refreshStats = () => {
            const now = performance.now();
            const insertionMark = performance.getEntriesByName("insertion", "mark");
            const nextThroughput = insertionMark.length / (now / 1000 / 60);
            performance.clearMarks();
            setThroughput(nextThroughput);
        };
        const interval = setInterval(refreshStats, 1000);
        return () => {
            clearInterval(interval);
        };
    }, []);
    if (percentage >= 100) {
        return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: ["Inserted ", formatQuantity(insertionCount), " records"] }), _jsxs(Text, { children: ["Elapsed: ", formatMinutes(elapsed / 1000 / 60), " minute(s)"] }), _jsx(Text, { children: "Done!" })] }));
    }
    return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { children: ["Inserted ", formatQuantity(insertionCount)] }), _jsxs(Text, { children: ["\u00A0of\u00A0", recordCount === -1 ? "∞" : formatQuantity(recordCount)] }), _jsx(Text, { children: "\u00A0records" })] }), _jsxs(Text, { children: [throughput.toFixed(2), "/min"] }), _jsxs(Text, { children: ["Elapsed: ", formatMinutes(elapsed / 1000 / 60), " minute(s)"] }), _jsxs(Text, { children: ["ETA: ", Number.isFinite(eta) ? formatMinutes(eta) : "∞", " minute(s)"] }), _jsxs(Box, { paddingX: 1, children: [_jsx(ProgressBar, { value: percentage }), _jsxs(Text, { children: [percentage.toFixed(2), "%"] })] })] }));
};
export default WOFPrepare;
//# sourceMappingURL=index.js.map