// deno-lint-ignore-file no-explicit-any
import { requireLogin } from "../../core/auth.js";
import { resolveWorkspace, validatePath } from "../../core/context.js";
import { colors, Command, log, SEP, Table, windmillUtils, yamlParseFile, } from "../../../deps.js";
import * as wmill from "../../../gen/services.gen.js";
import { isSuperset } from "../../types.js";
import { readInlinePathSync } from "../../utils/utils.js";
const alreadySynced = [];
export async function pushApp(workspace, remotePath, localPath, message) {
    if (alreadySynced.includes(localPath)) {
        return;
    }
    alreadySynced.push(localPath);
    remotePath = remotePath.replaceAll(SEP, "/");
    let app = undefined;
    // deleting old app if it exists in raw mode
    try {
        app = await wmill.getAppByPath({
            workspace,
            path: remotePath,
        });
    }
    catch {
        //ignore
    }
    app.value.policy = undefined;
    if (!localPath.endsWith(SEP)) {
        localPath += SEP;
    }
    const path = localPath + "app.yaml";
    const localApp = (await yamlParseFile(path));
    function replaceInlineScripts(rec) {
        if (!rec) {
            return;
        }
        if (typeof rec == "object") {
            return Object.entries(rec).flatMap(([k, v]) => {
                if (k == "inlineScript" && typeof v == "object") {
                    const o = v;
                    if (o["content"] && o["content"].startsWith("!inline")) {
                        const basePath = localPath + o["content"].split(" ")[1];
                        o["content"] = readInlinePathSync(basePath);
                    }
                    if (o["lock"] && o["lock"].startsWith("!inline")) {
                        const basePath = localPath + o["lock"].split(" ")[1];
                        o["lock"] = readInlinePathSync(basePath);
                    }
                }
                else {
                    replaceInlineScripts(v);
                }
            });
        }
        return [];
    }
    replaceInlineScripts(localApp.value);
    await generatingPolicy(localApp.value, remotePath);
    if (app) {
        if (isSuperset(localApp, app)) {
            log.info(colors.green(`App ${remotePath} is up to date`));
            return;
        }
        log.info(colors.bold.yellow(`Updating app ${remotePath}...`));
        await wmill.updateApp({
            workspace,
            path: remotePath,
            requestBody: {
                deployment_message: message,
                ...localApp,
            },
        });
    }
    else {
        log.info(colors.yellow.bold("Creating new app..."));
        await wmill.createApp({
            workspace,
            requestBody: {
                path: remotePath,
                deployment_message: message,
                ...localApp,
            },
        });
    }
}
async function generatingPolicy(app, path) {
    log.info(colors.gray(`Generating fresh policy for app ${path}...`));
    try {
        app.policy = await windmillUtils.updatePolicy(app, undefined);
    }
    catch (e) {
        log.error(colors.red(`Error generating policy for app ${path}: ${e}`));
        throw e;
    }
}
async function list(opts) {
    const workspace = await resolveWorkspace(opts);
    await requireLogin(opts);
    let page = 0;
    const perPage = 10;
    const total = [];
    while (true) {
        const res = await wmill.listApps({
            workspace: workspace.workspaceId,
            page,
            perPage,
            includeDraftOnly: opts.includeDraftOnly ?? false,
        });
        page += 1;
        total.push(...res);
        if (res.length < perPage) {
            break;
        }
    }
    new Table()
        .header(["path", "summary"])
        .padding(2)
        .border(true)
        .body(total.map((x) => [x.path, x.summary]))
        .render();
}
async function push(opts, filePath, remotePath) {
    if (!validatePath(remotePath)) {
        return;
    }
    const workspace = await resolveWorkspace(opts);
    await requireLogin(opts);
    await pushApp(workspace.workspaceId, remotePath, filePath);
    log.info(colors.bold.underline.green("Flow pushed"));
}
const command = new Command()
    .description("app related commands")
    .action(list)
    .command("push", "push a local app ")
    .arguments("<file_path:string> <remote_path:string>")
    .action(push);
export default command;
