"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.openIssueListWeb = openIssueListWeb;
exports.buildIssueListWebUrl = buildIssueListWebUrl;
exports.resolveGiteaIssueListLabelIds = resolveGiteaIssueListLabelIds;
const browser_1 = require("../core/browser");
const catalog_1 = require("../i18n/catalog");
const constants_1 = require("../platform/constants");
const auth_1 = require("../platform/gitea/auth");
const project_ref_1 = require("../platform/gitea/project-ref");
const project_ref_2 = require("../platform/github/project-ref");
const project_ref_3 = require("../platform/gitlab/project-ref");
const gitea_ticket_tracker_client_support_1 = require("../platform/ticket-tracker/gitea-ticket-tracker-client-support");
async function openIssueListWeb(input) {
    const locale = input.locale ?? catalog_1.DEFAULT_APP_LOCALE;
    assertIssueListWebFiltersSupported(input.config, input.options, locale);
    const resolvedFilters = await resolveIssueListWebFilters(input, locale);
    const url = buildIssueListWebUrl({
        config: input.config,
        options: input.options,
        locale,
        ...(resolvedFilters !== undefined ? { resolvedFilters } : {}),
    });
    await (0, browser_1.openUrlInBrowser)(url);
    return url;
}
function buildIssueListWebUrl(input) {
    const locale = input.locale ?? catalog_1.DEFAULT_APP_LOCALE;
    assertIssueListWebFiltersSupported(input.config, input.options, locale);
    switch (input.config.ticketTracker.kind) {
        case "github":
            return buildGitHubIssueListWebUrl(input.config, input.options, locale);
        case "gitlab":
            return buildGitLabIssueListWebUrl(input.config, input.options, locale);
        case "gitea":
            return buildGiteaIssueListWebUrl(input.config, input.options, locale, input.resolvedFilters?.giteaLabelIds);
    }
}
async function resolveGiteaIssueListLabelIds(input) {
    const locale = input.locale ?? catalog_1.DEFAULT_APP_LOCALE;
    const project = (0, project_ref_1.parseGiteaProjectRef)(input.config.ticketTracker.projectRef, locale);
    const labels = await (0, gitea_ticket_tracker_client_support_1.collectPaginatedGiteaArray)({
        url: `${project.origin}/api/v1/repos/${encodeURIComponent(project.owner)}/${encodeURIComponent(project.repo)}/labels`,
        requestJsonWithHeaders: async (_method, url) => {
            const response = await fetch(url, {
                headers: {
                    authorization: (0, auth_1.toGiteaAuthorizationHeader)(input.credential),
                },
            });
            if (!response.ok) {
                throw await (0, gitea_ticket_tracker_client_support_1.createGiteaApiError)(response);
            }
            return {
                data: (await response.json()),
                headers: response.headers,
            };
        },
    });
    const idByName = new Map(labels.flatMap((label) => typeof label.id === "number" && typeof label.name === "string"
        ? [[label.name, label.id]]
        : []));
    const missingLabels = input.labelNames.filter((labelName) => !idByName.has(labelName));
    if (missingLabels.length > 0) {
        throw new Error((0, catalog_1.translate)(locale, "issue.command.list.webGiteaLabelNotFound", {
            labels: missingLabels.join(", "),
        }));
    }
    return input.labelNames.map((labelName) => {
        const labelId = idByName.get(labelName);
        if (labelId === undefined) {
            throw new Error((0, catalog_1.translate)(locale, "issue.command.list.webGiteaLabelNotFound", {
                labels: labelName,
            }));
        }
        return labelId;
    });
}
function buildGitHubIssueListWebUrl(config, options, locale) {
    const project = (0, project_ref_2.parseGitHubProjectRef)(config.ticketTracker.projectRef, locale);
    const url = new URL(`https://github.com/${project.owner}/${project.repo}/issues`);
    const terms = buildGitHubIssueSearchTerms(options);
    if (terms.length > 0) {
        url.searchParams.set("q", terms.join(" "));
    }
    return url.toString();
}
function buildGitLabIssueListWebUrl(config, options, locale) {
    const project = (0, project_ref_3.parseGitLabProjectRef)(config.ticketTracker.projectRef, locale);
    const url = new URL(`${project.origin}/${project.fullPath}/-/issues`);
    url.searchParams.set("state", formatGitLabIssueListState(normalizeWebIssueState(options.state)));
    url.searchParams.set("sort", "updated_desc");
    for (const label of options.labels ?? []) {
        url.searchParams.append("label_name[]", label);
    }
    const since = buildSinceTimestamp(options.days);
    if (since !== null) {
        url.searchParams.set("updated_after", since);
    }
    return url.toString();
}
function buildGiteaIssueListWebUrl(config, options, locale, labelIds) {
    const project = (0, project_ref_1.parseGiteaProjectRef)(config.ticketTracker.projectRef, locale);
    const url = new URL(`${project.origin}/${project.owner}/${project.repo}/issues`);
    url.searchParams.set("state", normalizeWebIssueState(options.state));
    const labels = options.labels ?? [];
    if (labels.length > 0) {
        if (labelIds === undefined || labelIds.length !== labels.length) {
            throw new Error((0, catalog_1.translate)(locale, "issue.command.list.webGiteaLabelIdsRequired"));
        }
        url.searchParams.set("labels", labelIds.join(","));
    }
    return url.toString();
}
function buildGitHubIssueSearchTerms(options) {
    const state = normalizeWebIssueState(options.state);
    return [
        "is:issue",
        ...(state === constants_1.PLATFORM_ISSUE_LIST_STATES.all ? [] : [`state:${state}`]),
        ...(options.labels ?? []).map((label) => `label:${formatGitHubSearchValue(label)}`),
        ...(options.days !== undefined
            ? [`updated:>=${buildSinceDate(options.days)}`]
            : []),
    ];
}
function normalizeWebIssueState(state) {
    return state ?? constants_1.PLATFORM_ISSUE_LIST_STATES.open;
}
function formatGitLabIssueListState(state) {
    if (state === constants_1.PLATFORM_ISSUE_LIST_STATES.open) {
        return "opened";
    }
    return state;
}
function formatGitHubSearchValue(value) {
    if (!/[\s":]/u.test(value)) {
        return value;
    }
    const escaped = value.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"');
    return `"${escaped}"`;
}
function buildSinceDate(days) {
    return new Date(Date.now() - days * 24 * 60 * 60 * 1_000)
        .toISOString()
        .slice(0, 10);
}
function buildSinceTimestamp(days) {
    if (days === undefined) {
        return null;
    }
    return new Date(Date.now() - days * 24 * 60 * 60 * 1_000).toISOString();
}
async function resolveIssueListWebFilters(input, locale) {
    const labels = input.options.labels ?? [];
    if (input.config.ticketTracker.kind !== "gitea" || labels.length === 0) {
        return undefined;
    }
    if (input.resolveGiteaLabelIds === undefined) {
        throw new Error((0, catalog_1.translate)(locale, "issue.command.list.webGiteaLabelIdsRequired"));
    }
    return {
        giteaLabelIds: await input.resolveGiteaLabelIds(labels),
    };
}
function assertIssueListWebFiltersSupported(config, options, locale) {
    if (config.ticketTracker.kind === "gitea" && options.days !== undefined) {
        throw new Error((0, catalog_1.translate)(locale, "issue.command.list.webGiteaDaysUnsupported"));
    }
}
