/* jscpd:ignore-start */
import * as azdev from "azure-devops-node-api";
import { TicketProviderRoot } from "./ticketProviderRoot.js";
import c from "chalk";
import sortArray from "sort-array";
import { getBranchMarkdown, getOrgMarkdown } from "../utils/notifUtils.js";
import { extractRegexMatches, uxLog } from "../utils/index.js";
import { SfError } from "@salesforce/core";
import { getEnvVar } from "../../config/index.js";
/* jscpd:ignore-end */
export class AzureBoardsProvider extends TicketProviderRoot {
    serverUrl;
    azureApi;
    teamProject;
    constructor() {
        super();
        // Azure server url must be provided in SYSTEM_COLLECTIONURI. ex: https:/dev.azure.com/mycompany
        this.serverUrl = getEnvVar("SYSTEM_COLLECTIONURI");
        // a Personal Access Token must be defined
        this.token = getEnvVar("CI_SFDX_HARDIS_AZURE_TOKEN") || getEnvVar("SYSTEM_ACCESSTOKEN");
        this.teamProject = getEnvVar("SYSTEM_TEAMPROJECT");
        if (this.serverUrl && this.token && this.teamProject) {
            this.isActive = true;
        }
        if (this.isActive) {
            const authHandler = azdev.getHandlerFromToken(this.token || "");
            this.azureApi = new azdev.WebApi(this.serverUrl || "", authHandler);
        }
    }
    static isAvailable() {
        if (
        // Basic auth
        getEnvVar("SYSTEM_COLLECTIONURI") &&
            getEnvVar("SYSTEM_ACCESSTOKEN") &&
            getEnvVar("SYSTEM_TEAMPROJECT")) {
            return true;
        }
        return false;
    }
    getLabel() {
        return "sfdx-hardis JIRA connector";
    }
    static async getTicketsFromString(text, prInfo) {
        const tickets = [];
        // Extract Azure Boards Work Items
        const azureBoardsUrlRegex = /(https:\/\/.*\/_workitems\/edit\/[0-9]+)/g;
        const azureBoardUrlsMatches = await extractRegexMatches(azureBoardsUrlRegex, text);
        for (const azureTicketUrl of azureBoardUrlsMatches) {
            const pattern = /https:\/\/.*\/_workitems\/edit\/([0-9]+)/;
            const match = azureTicketUrl.match(pattern);
            if (match) {
                if (!tickets.some((ticket) => ticket.url === azureTicketUrl)) {
                    tickets.push({
                        provider: "AZURE",
                        url: azureTicketUrl,
                        id: match[1],
                    });
                }
            }
        }
        const ticketsSorted = sortArray(tickets, { by: ["id"], order: ["asc"] });
        if (!this.isAvailable()) {
            return ticketsSorted;
        }
        // Get tickets from Azure commits
        if (prInfo?.providerInfo?.commits) {
            const azureBoardsProvider = new AzureBoardsProvider();
            const azureApi = azureBoardsProvider.azureApi;
            const azureGitApi = await azureApi.getGitApi();
            const repositoryId = getEnvVar("BUILD_REPOSITORY_ID") || "";
            const commitIds = prInfo?.providerInfo?.commits.filter((commit) => commit.hash).map((commit) => commit.hash);
            const azureCommits = [];
            for (const commitId of commitIds) {
                const commitRefs = await azureGitApi.getCommits(repositoryId, { fromCommitId: commitId, toCommitId: commitId, includeWorkItems: true });
                azureCommits.push(...commitRefs);
            }
            for (const commit of azureCommits) {
                for (const workItem of commit?.workItems || []) {
                    if (!tickets.some((ticket) => ticket.id === workItem.id)) {
                        tickets.push({
                            provider: "AZURE",
                            url: workItem.url || "",
                            id: workItem.id || "",
                        });
                    }
                }
            }
        }
        // Get tickets from Azure PR
        if (prInfo?.providerInfo?.workItemRefs?.length) {
            for (const workItemRef of prInfo.providerInfo.workItemRefs) {
                if (!tickets.some((ticket) => ticket.id === workItemRef.id)) {
                    tickets.push({
                        provider: "AZURE",
                        url: workItemRef.url,
                        id: workItemRef.id,
                    });
                }
            }
        }
        return ticketsSorted;
    }
    // Call Azure Work Items apis to gather more information from the ticket identifiers
    async collectTicketsInfo(tickets) {
        const azureTicketsNumber = tickets.filter((ticket) => ticket.provider === "AZURE").length;
        if (azureTicketsNumber > 0) {
            uxLog("action", this, c.cyan(`[AzureBoardsProvider] Now trying to collect ${azureTicketsNumber} tickets infos from Azure Boards Server ` +
                process.env.SYSTEM_COLLECTIONURI +
                " ..."));
        }
        const azureWorkItemApi = await this.azureApi.getWorkItemTrackingApi(this.serverUrl || "");
        for (const ticket of tickets) {
            if (ticket.provider === "AZURE") {
                const ticketInfo = await azureWorkItemApi.getWorkItem(Number(ticket.id));
                if (ticketInfo && ticketInfo?.fields) {
                    ticket.foundOnServer = true;
                    ticket.subject = ticketInfo.fields["System.Title"] || "";
                    ticket.status = ticketInfo.fields["System.State"] || "";
                    ticket.statusLabel = ticketInfo.fields["System.State"] || "";
                    if (ticketInfo?._links && ticketInfo._links["html"] && ticketInfo._links["html"]["href"]) {
                        ticket.url = ticketInfo?._links["html"]["href"];
                    }
                    uxLog("log", this, c.grey("[AzureBoardsProvider] Collected data for Work Item " + ticket.id));
                }
                else {
                    uxLog("warning", this, c.yellow("[AzureBoardsProvider] Unable to get Azure Boards WorkItem " + ticket.id + "\n" + c.grey(JSON.stringify(ticketInfo))));
                }
            }
        }
        return tickets;
    }
    async postDeploymentComments(tickets, org, pullRequestInfo) {
        uxLog("action", this, c.cyan(`[AzureBoardsProvider] Try to post comments on ${tickets.length} work items...`));
        const orgMarkdown = await getOrgMarkdown(org, "html");
        const branchMarkdown = await getBranchMarkdown("html");
        const tag = await this.getDeploymentTag();
        const commentedTickets = [];
        const taggedTickets = [];
        const azureWorkItemApi = await this.azureApi.getWorkItemTrackingApi(this.serverUrl || "");
        for (const ticket of tickets) {
            if (ticket.foundOnServer) {
                let azureBoardsComment = `Deployed from branch ${branchMarkdown} to org ${orgMarkdown}`;
                if (pullRequestInfo) {
                    const prUrl = pullRequestInfo.webUrl || "";
                    if (prUrl) {
                        const prAuthor = pullRequestInfo.authorName;
                        azureBoardsComment += `<br/><br/>PR: <a href="${prUrl}">${pullRequestInfo.title}</a>` + (prAuthor ? ` by ${prAuthor}` : "");
                    }
                }
                // Post comment
                try {
                    const commentPostRes = await azureWorkItemApi.addComment({ text: azureBoardsComment }, this.teamProject || "", Number(ticket.id));
                    if (commentPostRes?.id && commentPostRes?.id > 0) {
                        commentedTickets.push(ticket);
                    }
                    else {
                        throw new SfError("commentPostRes: " + commentPostRes);
                    }
                }
                catch (e6) {
                    uxLog("warning", this, c.yellow(`[AzureBoardsProvider] Error while posting comment on ${ticket.id}\n${e6.message}\n${c.grey(e6.stack)}`));
                }
                // Add tag
                try {
                    const patchDocument = [
                        {
                            op: "add",
                            path: "/fields/System.Tags",
                            value: tag,
                        },
                    ];
                    const workItem = await azureWorkItemApi.updateWorkItem({}, patchDocument, Number(ticket.id), this.teamProject || "");
                    if (workItem?.id && workItem?.id > 0) {
                        taggedTickets.push(ticket);
                    }
                    else {
                        throw new SfError("tag workItem: " + workItem);
                    }
                }
                catch (e6) {
                    uxLog("warning", this, c.yellow(`[AzureBoardsProvider] Error while adding tag ${tag} on ${ticket.id}\n${e6.message} \n${c.grey(e6.stack)} `));
                }
            }
        }
        uxLog("log", this, c.grey(`[AzureBoardsProvider] Posted comments on ${commentedTickets.length} work item(s): ` + commentedTickets.map((ticket) => ticket.id).join(", ")));
        uxLog("log", this, c.grey(`[AzureBoardsProvider] Added tag ${tag} on ${taggedTickets.length} work item(s): ` + taggedTickets.map((ticket) => ticket.id).join(", ")));
        return tickets;
    }
}
//# sourceMappingURL=azureBoardsProvider.js.map