/*
 * Copyright (C) 2020 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import {stat, unlink} from "fs";
import path from "path";
import util from "util";
import which from "which";
import {execFile, spawn} from "child_process";
import { HttpsProxyAgent } from 'https-proxy-agent';
import LogLevel from "@slack/rtm-api";
import SlackRTMAPI from "@slack/rtm-api";
import AsyncTaskQueue from "./AsyncTaskQueue.mjs";
import {buildGitWebkitRevertCommand, extractCommandAndArgs, extractRevisionsAndReason,
    extractTextIfMentioned, parseBugId, parsePRUrl} from "./CommandParser.mjs";
import {dataLogLn, escapeForSlackText, isASCII, rootDirectoryOfWebKit} from "./Utility.mjs";

const defaultTaskLimit = 10;
const defaultPullPeriod = 60 * 1000 * 60;
const defaultTimeoutForRevert = 60 * 1000 * 10;

const execFileAsync = util.promisify(execFile);
const statAsync = util.promisify(stat);
const unlinkAsync = util.promisify(unlink);

export default class WebKitBot {
    postMessage(options)
    {
        return this._web.chat.postMessage({
            unfurl_links: false,
            unfurl_media: false,
            ...options,
        });
    }

    constructor(webClient, auth)
    {
        this._taskQueue = new AsyncTaskQueue(defaultTaskLimit);
        this._web = webClient;
        this._auth = auth;

        this._commands = new Map;

        let revertCommand = {
            description: "Reverts the specified revision(s) by creating a GitHub pull request. Optionally reuse an existing bug by passing its URL in place of a reason.",
            usage: `\`revert REVISION [REVISIONS] REASON\` or \`revert REVISION [REVISIONS] BUG_URL\`
    Examples:
    • \`revert 260220@main Ensure it is working after refactoring\`
    • \`revert 260220@main,260221@main Ensure it is working after refactoring\`
    • \`revert 308300@main https://bugs.webkit.org/show_bug.cgi?id=308859\``,
            operation: this.revertCommand.bind(this),
        };
        this._commands.set("rollout", revertCommand);
        this._commands.set("revert", revertCommand);
        this._commands.set("dry-revert", {
            description: "Parse revert message, but do not revert actually.",
            usage: `\`dry-revert REVISION [REVISIONS] REASON\` or \`dry-revert REVISION [REVISIONS] BUG_URL\`
    Examples:
    • \`dry-revert 260220@main Ensure it is working after refactoring\`
    • \`dry-revert 308300@main https://bugs.webkit.org/show_bug.cgi?id=308859\``,
            operation: this.dryRevertCommand.bind(this),
        });
        this._commands.set("ping", {
            description: "Responds with pong to check if WebKitBot is alive/working",
            usage: "`ping`",
            operation: this.pingCommand.bind(this),
        });
        this._commands.set("pull", {
            description: "Pulls the latest checkout of WebKit checkout for reverting queue.",
            usage: "`pull`",
            operation: this.pullCommand.bind(this),
        });

        this._commands.set("help", {
            description: "Provides help on my individual commands.",
            usage: "`help [COMMAND]`",
            operation: this.helpCommand.bind(this),
        });
        this._commands.set("status", {
            description: "Shows current reverting queue status.",
            usage: "`status`",
            operation: this.statusCommand.bind(this),
        });
        this._commands.set("hi", {
            description: "Responds with hi.",
            usage: "`hi`",
            operation: this.hiCommand.bind(this),
        });
        this._commands.set("yt?", {
            description: "Responds with yes.",
            usage: "`yt?`",
            operation: this.youThereCommand.bind(this),
        });

        const proxy = new HttpsProxyAgent(process.env.http_proxy);
        this._rtm = new SlackRTMAPI.RTMClient(process.env.SLACK_TOKEN, { agent: proxy, logLevel: LogLevel.DEBUG });
        this._rtm.on("message", async (event) => {
            if (event.type !== "message")
                return;

            // If message has subtype, this is not an usual message.
            if (event.subtype)
                return;

            let text = extractTextIfMentioned(event.text, this._auth.user_id);
            if (text) {
                let {command, args} = extractCommandAndArgs(text);
                let operation = this._commands.get(command);
                if (operation)
                    await operation.operation(event, command, args);
                else
                    await this.unknownCommand(event, command, args);
            }
        });
        setInterval(() => {
            this._taskQueue.postOrFailWhenExceedingLimit({
                command: "pull",
            });
        }, defaultPullPeriod);
    }

    async revertCommand(event, command, args)
    {
        let {revisions, reason} = extractRevisionsAndReason(args);

        const usingGitWebkit = process.env.USE_GIT_WEBKIT_REVERT === "true";

        // When routing through git-webkit, check if the "reason" is actually a
        // bug URL to reuse as the tracking issue.
        let issueUrl = null;
        if (usingGitWebkit && reason) {
            let bugId = parseBugId(reason);
            if (bugId) {
                issueUrl = `https://bugs.webkit.org/show_bug.cgi?id=${bugId}`;
                reason = "";
            }
        }

        if (!issueUrl && !isASCII(reason)) {
            await this.postMessage({
                channel: event.channel,
                text: `<@${event.user}> webkit-patch only accepts an ASCII string for reason: \`${escapeForSlackText(reason)}\``,
            });
            return;
        }

        if (usingGitWebkit && !reason && !issueUrl) {
            await this.postMessage({
                channel: event.channel,
                text: `<@${event.user}> Please provide a reason or a bug URL.`,
            });
            return;
        }

        dataLogLn(revisions, reason, issueUrl);
        if (revisions.length) {
            try {
                await this.postMessage({
                    channel: event.channel,
                    text: `<@${event.user}> Preparing revert for ${revisions.map((revision) => {
                        let revRepr = revision;
                        if (revRepr.match(/^\d+$/))
                            revRepr = `r${revRepr}`;
                        return `<${escapeForSlackText(`https://commits.webkit.org/${revRepr}|${revRepr}`)}>`;
                    }).join(" ")} ...`,
                });
                let result = await this._taskQueue.postOrFailWhenExceedingLimit({
                    command: "revert",
                    revisions,
                    reason,
                    issueUrl,
                });

                let successMessage;
                if (result.startsWith("https://github.com/"))
                    successMessage = `<@${event.user}> Created revert PR: ${escapeForSlackText(result)}`;
                else
                    successMessage = `<@${event.user}> Created a revert patch https://webkit.org/b/${escapeForSlackText(result)}`;

                await this.postMessage({
                    channel: event.channel,
                    text: successMessage,
                });
            } catch (error) {
                console.error(error);
                let stderr = error.stderr;
                let stdout = error.stdout;
                console.error("STDERR ", stderr);
                if (typeof stderr === "string") {
                    if (usingGitWebkit && stderr.indexOf("CONFLICT") !== -1) {
                        let conflictFiles = [];
                        for (let line of stderr.split("\n")) {
                            let match = line.match(/CONFLICT.*Merge conflict in (.+)/);
                            if (match)
                                conflictFiles.push(match[1].trim());
                        }
                        // Check if a bug was already created before the conflict
                        let createdBugMatch = typeof stdout === "string" && stdout.match(/https:\/\/bugs\.webkit\.org\/show_bug\.cgi\?id=\d+/);
                        let message = `<@${event.user}> Failed to create revert PR due to merge conflicts.`;
                        if (conflictFiles.length)
                            message += `\nConflicting files:\n${escapeForSlackText(conflictFiles.map(f => `  • ${f}`).join("\n"))}`;
                        if (createdBugMatch)
                            message += `\nA bug was created at ${escapeForSlackText(createdBugMatch[0])}! Please close or reuse this bug for your revert.`;
                        await this.postMessage({
                            channel: event.channel,
                            text: message,
                        });
                        return;
                    }
                    if (usingGitWebkit && stderr.indexOf("already be reverted") !== -1) {
                        await this.postMessage({
                            channel: event.channel,
                            text: `<@${event.user}> The commit(s) appear to already be reverted.`,
                        });
                        return;
                    }
                    // webkit-patch: merge conflict
                    {
                        let index = stderr.indexOf("Failed to apply reverse diff for revision");
                        if (index !== -1) {
                            let lines = stderr.slice(index).split("\n");
                            lines.shift();
                            let files = [];
                            for (let line of lines) {
                                try {
                                    await statAsync(path.join(process.env.webkitWorkingDirectory, line));
                                    files.push(line);
                                } catch {
                                    // THis is not a file.
                                    break;
                                }
                            }
                            if (files.length !== 0) {
                                await this.postMessage({
                                    channel: event.channel,
                                    text: `<@${event.user}> Failed to create revert patch because of the following conflicts:
\`\`\`
${escapeForSlackText(files.join("\n"))}\`\`\``,
                                });
                                return;
                            }
                        }
                    }
                    {
                        let index = stderr.indexOf("You are not authorized to access bug");
                        if (index !== -1) {
                            let line = stderr.slice(index).split("\n")[0].trim();
                            let matched = /#(\d+)/.match(line);
                            await this.postMessage({
                                channel: event.channel,
                                text: `<@${event.user}> Failed to create revert patch. Please ensure commit-queue@webkit.org is authorized to access ${matched ? ("bug " + escapeForSlackText(matched[1])) : "the bug"}.`
                            });
                            return;
                        }
                    }
                }
                await this.postMessage({
                    channel: event.channel,
                    text: `<@${event.user}> Failed to create revert patch.` + (stderr ? `
\`\`\`
${escapeForSlackText(stderr)}\`\`\`` : ""),
                });
            }
            return;
        }

        dataLogLn("Failed to parse revision and reason from: ", args);
        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> Failed to parse revision and reason: \`${escapeForSlackText(args.join(" "))}\``,
        });
    }

    async dryRevertCommand(event, command, args)
    {
        let {revisions, reason} = extractRevisionsAndReason(args);

        // Check if the "reason" is actually a bug URL
        let issueUrl = null;
        if (reason) {
            let bugId = parseBugId(reason);
            if (bugId) {
                issueUrl = `https://bugs.webkit.org/show_bug.cgi?id=${bugId}`;
                reason = "";
            }
        }

        if (!issueUrl && !isASCII(reason)) {
            await this.postMessage({
                channel: event.channel,
                text: `<@${event.user}> webkit-patch only accepts an ASCII string for reason: \`${escapeForSlackText(reason)}\``,
            });
            return;
        }

        if (!revisions.length) {
            let detail = issueUrl
                ? `issue = \`${escapeForSlackText(issueUrl)}\``
                : `reason = \`${escapeForSlackText(reason)}\``;
            await this.postMessage({
                channel: event.channel,
                text: `<@${event.user}> No revision is found: ${detail}`,
            });
            return;
        }

        let message;
        if (issueUrl)
            message = `revisions = \`${escapeForSlackText(revisions.join(","))}\`, issue = \`${escapeForSlackText(issueUrl)}\``;
        else
            message = `revisions = \`${escapeForSlackText(revisions.join(","))}\`, reason = \`${escapeForSlackText(reason)}\``;

        if (process.env.USE_GIT_WEBKIT_REVERT === "true") {
            let gitWebkitArgs = buildGitWebkitRevertCommand("git-webkit", revisions, reason, issueUrl);
            message += `\nRevert command: \`${escapeForSlackText(gitWebkitArgs.join(" "))}\``;
        }

        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> ${message}`,
        });
    }

    async pullCommand(event, command, args)
    {
        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> Preparing pulling the latest WebKit checkout.`,
        });
        await this._taskQueue.postOrFailWhenExceedingLimit({
            command: "pull",
        });
        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> Pulled the latest checkout.`,
        });
    }

    async pingCommand(event, command, args)
    {
        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> pong`,
        });
    }

    async helpCommand(event, command, args)
    {
        if (args.length) {
            let commandName = args[0];
            let operation = this._commands.get(commandName);
            if (operation) {
                await this.postMessage({
                    channel: event.channel,
                    text: `<@${event.user}> \`${escapeForSlackText(commandName)}\`: ${escapeForSlackText(operation.description)}
Usage: ${escapeForSlackText(operation.usage)}`,
                });
            } else {
                await this.postMessage({
                    channel: event.channel,
                    text: `<@${event.user}> Unknown command \`${escapeForSlackText(commandName)}\``,
                });
            }
        } else {
            let commandNames = [];
            for (let key of this._commands.keys())
                commandNames.push("`" + key + "`");
            await this.postMessage({
                channel: event.channel,
                text: `<@${event.user}> Available commands: ${escapeForSlackText(commandNames.join(", "))}
Type \`help COMMAND\` for help on my individual commands.`,
            });
        }
    }

    async statusCommand(event, command, args)
    {
        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> ${escapeForSlackText(String(this._taskQueue.length))} requests in queue.`,
        });
    }

    async hiCommand(event, command, args)
    {
        await this.postMessage({
            channel: event.channel,
            text: `Hi <@${event.user}>!`,
        });
    }

    async youThereCommand(event, command, args)
    {
        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> yes`,
        });
    }

    async unknownCommand(event, command, args)
    {
        dataLogLn("Unknown command: ", command);
        await this.postMessage({
            channel: event.channel,
            text: `<@${event.user}> Unknown command \`${escapeForSlackText(command)}\``,
        });
    }

    execInWebKitDirectorySimple(command, args)
    {
        return new Promise((resolve, reject) => {
            let task = spawn(command, args, {
                cwd: process.env.webkitWorkingDirectory,
                env: {
                    PATH: process.env.PATH,
                    HOME: process.env.HOME || "/root",
                    // Needed to suppress long utf-8 warnings in logs
                    LC_ALL: "C.UTF-8",
                    LANG: "C.UTF-8",
                },
                stdio: "inherit",
            });
            task.on("close", (code) => {
                if (!code)
                    resolve(code);
                else
                    reject(code);
            });
        });
    }

    // Remove orphaned *.lock files from a crashed git process; safe because the AsyncTaskQueue guarantees no git process is running here.
    async clearStaleGitLocks()
    {
        const gitDir = path.join(process.env.webkitWorkingDirectory, ".git");
        const lockPaths = [
            path.join(gitDir, "index.lock"),
            path.join(gitDir, "HEAD.lock"),
            path.join(gitDir, "config.lock"),
            path.join(gitDir, "packed-refs.lock"),
            path.join(gitDir, "refs", "heads", "main.lock"),
        ];
        for (let lockPath of lockPaths) {
            try {
                await unlinkAsync(lockPath);
                dataLogLn("Removed stale git lock: " + lockPath);
            } catch (error) {
                if (error.code !== "ENOENT")
                    dataLogLn("Warning: could not remove git lock " + lockPath + ": " + error.message);
            }
        }
    }

    async cleanUpWorkingCopy()
    {
        await this.clearStaleGitLocks();

        dataLogLn("1. Resetting");
        await this.execInWebKitDirectorySimple("git", ["reset", "--hard"]);

        dataLogLn("2. Cleaning");
        await this.execInWebKitDirectorySimple("git", ["clean", "-df"]);

        dataLogLn("3. Fetching");
        await this.execInWebKitDirectorySimple("git", ["fetch", "origin"]);

        dataLogLn("4. Checkout out origin/main");
        await this.execInWebKitDirectorySimple("git", ["checkout", "origin/main", "-f"]);

        dataLogLn("5. Deleting local 'main' ref");
        await this.execInWebKitDirectorySimple("git", ["branch", "-D", "main"]);

        dataLogLn("6. Creating local 'main' ref");
        await this.execInWebKitDirectorySimple("git", ["checkout", "origin/main", "-b", "main"]);

        dataLogLn("7. Cleaning up leftover branches");
        try {
            let {stdout} = await execFileAsync("git", ["for-each-ref", "--format", "%(refname:short)", "refs/heads/"], {
                cwd: process.env.webkitWorkingDirectory,
            });
            for (let branch of stdout.split("\n").filter(b => b && b !== "main")) {
                dataLogLn("Deleting branch:" + branch);
                await execFileAsync("git", ["branch", "-D", branch], {
                    cwd: process.env.webkitWorkingDirectory,
                });
            }
        } catch (error) {
            dataLogLn("Warning: Failed to clean up branches:" + error.message);
        }
    }

    async generateRevertingPatchWithGitWebkit(revisions, reason, issueUrl = null)
    {
        dataLogLn("Reverting with git-webkit: ", revisions, reason, issueUrl);

        if (!issueUrl && reason.startsWith("-"))
            throw new Error(`The revert reason may not begin with - ("${reason}")`);

        await this.cleanUpWorkingCopy();

        dataLogLn("Creating revert PR with git-webkit");
        let results;
        try {
            const gitWebkitPath = path.resolve("BotWebKit", "Tools", "Scripts", "git-webkit");
            var pythonPath = which.sync("python3");

            let args = buildGitWebkitRevertCommand(gitWebkitPath, revisions, reason, issueUrl);

            console.log("Running: " + pythonPath + " " + args.join(" "));

            results = await new Promise((resolve, reject) => {
                let stdout = "";
                let stderr = "";
                let task = spawn(pythonPath, args, {
                    cwd: process.env.webkitWorkingDirectory,
                    env: {
                        GIT_AUTHOR_NAME: "WebKit Revert Bot",
                        GIT_AUTHOR_EMAIL: "revert-bot@webkit.org",
                        GIT_COMMITTER_NAME: "WebKit Revert Bot",
                        GIT_COMMITTER_EMAIL: "revert-bot@webkit.org",
                        GIT_EDITOR: "true",
                        GITHUB_COM_USERNAME: process.env.GITHUB_COM_USERNAME,
                        GITHUB_COM_TOKEN: process.env.GITHUB_COM_TOKEN,
                        BUGS_WEBKIT_ORG_USERNAME: process.env.BUGS_WEBKIT_ORG_USERNAME,
                        BUGS_WEBKIT_ORG_PASSWORD: process.env.BUGS_WEBKIT_ORG_PASSWORD,
                        http_proxy: process.env.http_proxy,
                        https_proxy: process.env.http_proxy,
                        PATH: process.env.PATH,
                        HOME: process.env.HOME || "/root",
                    },
                    timeout: defaultTimeoutForRevert,
                });
                task.stdout.on("data", (data) => {
                    process.stdout.write(data);
                    stdout += data.toString();
                });
                task.stderr.on("data", (data) => {
                    process.stderr.write(data);
                    stderr += data.toString();
                });
                task.on("close", (code) => {
                    if (code === 0)
                        resolve({stdout, stderr});
                    else {
                        let error = new Error(`git-webkit exited with code ${code}`);
                        error.stdout = stdout;
                        error.stderr = stderr;
                        reject(error);
                    }
                });
                task.on("error", (error) => {
                    error.stdout = stdout;
                    error.stderr = stderr;
                    reject(error);
                });
            });
        } catch (error) {
            dataLogLn(error);
            let newError = new Error("git-webkit revert command failed");
            newError.stderr = error.stderr;
            newError.stdout = error.stdout;
            throw newError;
        }

        // stdout/stderr were already streamed live above; just parse the
        // captured output for the PR URL (don't re-dump it).
        let {stdout, stderr} = results;
        let prUrl = parsePRUrl(stdout) || parsePRUrl(stderr);
        if (prUrl)
            return prUrl;

        throw new Error("PR URL not found in git-webkit output");
    }

    async generateRevertingPatch(revisions, reason, issueUrl = null)
    {
        if (process.env.USE_GIT_WEBKIT_REVERT === "true")
            return this.generateRevertingPatchWithGitWebkit(revisions, reason, issueUrl);

        dataLogLn("Reverting ", revisions, reason);
        let revisionsArgument = revisions.join(" ");

        if (reason.startsWith("-"))
            throw new Error(`The revert reason may not begin with - ("${reason}")`);

        await this.cleanUpWorkingCopy();

        dataLogLn("7. Creating revert patch ", revisions, reason);
        let results;
        try {
            const webkitPatchPath = path.resolve("BotWebKit", "Tools", "Scripts", "webkit-patch");
            var pythonPath = which.sync('python3')
            results = await execFileAsync(pythonPath, [
                webkitPatchPath,
                "create-revert",
                "--force-clean",
                // In principle, we should pass --non-interactive here, but it
                // turns out that create-revert doesn't need it yet.  We can't
                // pass it prophylactically because we reject unrecognized command
                // line switches.
                "--parent-command=sheriff-bot",
                revisionsArgument,
                reason,
            ], {
                cwd: process.env.webkitWorkingDirectory,
                env: {
                    CHANGE_LOG_NAME: "Commit Queue",
                    CHANGE_LOG_EMAIL_ADDRESS: "commit-queue@webkit.org",
                    WEBKIT_BUGZILLA_USERNAME: process.env.webkitBugzillaUsername,
                    WEBKIT_BUGZILLA_PASSWORD: process.env.webkitBugzillaPassword,
                    http_proxy: process.env.http_proxy,
                    https_proxy: process.env.http_proxy,
                },
                timeout: defaultTimeoutForRevert,
                maxBuffer: 1024 * 1024 * 50,
            });
        } catch (error) {
            dataLogLn(error);
            let newError = new Error("Revert command failed");
            newError.stderr = error.stderr;
            throw newError;
        }
        let {stdout, stderr} = results;
        dataLogLn(stdout);
        dataLogLn(stderr);
        {
            let bugId = parseBugId(stdout);
            if (bugId !== null)
                return bugId;
        }
        {
            let bugId = parseBugId(stderr);
            if (bugId !== null)
                return bugId;
        }
        throw new Error("bug-id cannot be found");
    }

    async action(task)
    {
        dataLogLn(task);
        switch (task.command) {
        case "revert": {
            let {revisions, reason, issueUrl} = task;
            return this.generateRevertingPatch(revisions, reason, issueUrl);
        }
        case "pull":
            return this.cleanUpWorkingCopy();
        }
        throw new Error(`${task.command} is undefined action`);
    }

    static async create(webClient, auth)
    {
        let bot = new WebKitBot(webClient, auth);
        await bot._rtm.start();
        return bot;
    }

    static async main(webClient, auth)
    {
        let bot = await WebKitBot.create(webClient, auth);
        while (true) {
            let {task, resolve, reject} = await bot._taskQueue.take();
            try {
                let result = await bot.action(task);
                resolve(result);
            } catch (error) {
                reject(error);
            }
        }
    }
}
