// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

import { test, expect } from "@perspective-dev/test";
import { describeDuckDB } from "./setup.js";

describeDuckDB("combined operations", (getClient) => {
    test("group_by + filter + sort", async function () {
        const table = await getClient().open_table("memory.superstore");
        const view = await table.view({
            columns: ["Sales"],
            group_by: ["Category"],
            filter: [["Region", "==", "West"]],
            sort: [["Sales", "desc"]],
            aggregates: { Sales: "sum" },
        });
        const json = await view.to_json();
        expect(json).toEqual([
            { __ROW_PATH__: [], Sales: 725457.8245000006 },
            {
                __ROW_PATH__: ["Furniture"],
                Sales: 252612.7435000003,
            },
            {
                __ROW_PATH__: ["Technology"],
                Sales: 251991.83199999997,
            },
            {
                __ROW_PATH__: ["Office Supplies"],
                Sales: 220853.24900000007,
            },
        ]);
        await view.delete();
    });

    test("split_by + group_by + filter", async function () {
        const table = await getClient().open_table("memory.superstore");
        const view = await table.view({
            columns: ["Sales"],
            group_by: ["Category"],
            split_by: ["Region"],
            filter: [["Quantity", ">", 3]],
            aggregates: { Sales: "sum" },
        });

        const paths = await view.column_paths();
        expect(paths).toEqual([
            "Central_Sales",
            "East_Sales",
            "South_Sales",
            "West_Sales",
        ]);

        const numRows = await view.num_rows();
        expect(numRows).toBe(4);

        const json = await view.to_json();
        expect(json).toEqual([
            {
                __ROW_PATH__: [],
                "Central|Sales": 332883.0567999998,
                "East|Sales": 455143.735,
                "South|Sales": 274208.7699999999,
                "West|Sales": 470561.28350000136,
            },
            {
                __ROW_PATH__: ["Furniture"],
                "Central|Sales": 111457.73279999988,
                "East|Sales": 140376.95899999997,
                "South|Sales": 80859.618,
                "West|Sales": 165219.5734999998,
            },
            {
                __ROW_PATH__: ["Office Supplies"],
                "Central|Sales": 103937.78599999992,
                "East|Sales": 135823.893,
                "South|Sales": 84393.3579999999,
                "West|Sales": 140206.93099999975,
            },
            {
                __ROW_PATH__: ["Technology"],
                "Central|Sales": 117487.53800000002,
                "East|Sales": 178942.883,
                "South|Sales": 108955.79400000005,
                "West|Sales": 165134.77900000007,
            },
        ]);

        await view.delete();
    });

    test("split_by only", async function () {
        const table = await getClient().open_table("memory.superstore");
        const view = await table.view({
            columns: ["Sales"],
            split_by: ["Region"],
            filter: [["Quantity", ">", 3]],
        });

        const paths = await view.column_paths();
        expect(paths).toEqual([
            "Central_Sales",
            "East_Sales",
            "South_Sales",
            "West_Sales",
        ]);

        const numRows = await view.num_rows();
        expect(numRows).toBe(4284);
        const json = await view.to_json({ start_row: 0, end_row: 1 });
        expect(json).toEqual([
            {
                "Central|Sales": null,
                "East|Sales": null,
                "South|Sales": 957.5775,
                "West|Sales": null,
            },
        ]);

        await view.delete();
    });

    test("split_by only + sort", async function () {
        const table = await getClient().open_table("memory.superstore");
        const view = await table.view({
            columns: ["Sales"],
            split_by: ["Region"],
            sort: [["Sales", "desc"]],
            filter: [["Quantity", ">", 3]],
        });

        const paths = await view.column_paths();
        expect(paths).toEqual([
            "Central_Sales",
            "East_Sales",
            "South_Sales",
            "West_Sales",
        ]);

        const numRows = await view.num_rows();
        expect(numRows).toBe(4284);
        const json = await view.to_json({ start_row: 0, end_row: 1 });
        expect(json).toEqual([
            {
                "Central|Sales": null,
                "East|Sales": null,
                "South|Sales": 22638.48,
                "West|Sales": null,
            },
        ]);

        await view.delete();
    });

    test("flat + multi group_by + sort", async function () {
        const table = await getClient().open_table("memory.superstore");
        const view = await table.view({
            columns: ["Sales"],
            group_by: ["Region", "Category"],
            sort: [["Sales", "desc"]],
            aggregates: { Sales: "sum" },
            group_rollup_mode: "flat",
        });
        const json = await view.to_json({ start_row: 0, end_row: 5 });
        expect(json).toEqual([
            {
                __ROW_PATH__: ["West", "Furniture"],
                Sales: 252612.7435000003,
            },
            {
                __ROW_PATH__: ["West", "Technology"],
                Sales: 251991.83199999997,
            },
            {
                __ROW_PATH__: ["West", "Office Supplies"],
                Sales: 220853.24900000007,
            },
            {
                __ROW_PATH__: ["East", "Technology"],
                Sales: 264973.9810000003,
            },
            {
                __ROW_PATH__: ["East", "Furniture"],
                Sales: 208291.20400000009,
            },
        ]);
        await view.delete();
    });

    test("flat + multi group_by + split_by + sort", async function () {
        const table = await getClient().open_table("memory.superstore");
        const view = await table.view({
            columns: ["Sales"],
            group_by: ["Region", "Category"],
            split_by: ["Ship Mode"],
            sort: [["Sales", "desc"]],
            aggregates: { Sales: "sum" },
            group_rollup_mode: "flat",
        });
        const json = await view.to_json({ start_row: 0, end_row: 5 });
        expect(json).toEqual([
            {
                __ROW_PATH__: ["West", "Furniture"],
                "First Class|Sales": 40018.829499999985,
                "Same Day|Sales": 14527.978000000001,
                "Second Class|Sales": 54155.6555,
                "Standard Class|Sales": 143910.28049999996,
            },
            {
                __ROW_PATH__: ["West", "Technology"],
                "First Class|Sales": 61107.98900000001,
                "Same Day|Sales": 19218.053999999993,
                "Second Class|Sales": 38610.979999999996,
                "Standard Class|Sales": 133054.809,
            },
            {
                __ROW_PATH__: ["West", "Office Supplies"],
                "First Class|Sales": 28635.06999999996,
                "Same Day|Sales": 9857.678000000002,
                "Second Class|Sales": 52572.79199999999,
                "Standard Class|Sales": 129787.70900000003,
            },
            {
                __ROW_PATH__: ["East", "Technology"],
                "First Class|Sales": 47693.312999999995,
                "Same Day|Sales": 21349.464999999997,
                "Second Class|Sales": 29304.490000000005,
                "Standard Class|Sales": 166626.71300000005,
            },
            {
                __ROW_PATH__: ["East", "Furniture"],
                "First Class|Sales": 29410.643999999997,
                "Same Day|Sales": 12852.570999999996,
                "Second Class|Sales": 44035.937000000005,
                "Standard Class|Sales": 121992.05199999997,
            },
        ]);
        await view.delete();
    });

    test("expressions + group_by + sort", async function () {
        const table = await getClient().open_table("memory.superstore");
        const view = await table.view({
            columns: ["profitmargin"],
            group_by: ["Region"],
            expressions: { profitmargin: '"Profit" / "Sales" * 100' },
            sort: [["profitmargin", "desc"]],
            aggregates: { profitmargin: "avg" },
        });

        const json = await view.to_json();
        expect(json).toEqual([
            {
                __ROW_PATH__: [],
                profitmargin: 12.031392972104467,
            },
            {
                __ROW_PATH__: ["West"],
                profitmargin: 21.948661793784012,
            },
            {
                __ROW_PATH__: ["East"],
                profitmargin: 16.722695960406636,
            },
            {
                __ROW_PATH__: ["South"],
                profitmargin: 16.35190329218107,
            },
            {
                __ROW_PATH__: ["Central"],
                profitmargin: -10.407293926323575,
            },
        ]);

        await view.delete();
    });
});
