import Express from "../Utils/Express";
import Response from "../Utils/Response";
import BadRequestException from "../../Types/Exception/BadRequestException";
import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
import BadDataException from "../../Types/Exception/BadDataException";
import { AppApiClientUrl, AppVersion, DashboardClientUrl, HomeClientUrl, Host, MicrosoftTeamsAppClientId, MicrosoftTeamsAppClientSecret, } from "../EnvironmentConfig";
import URL from "../../Types/API/URL";
import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
import API from "../../Utils/API";
import WorkspaceProjectAuthTokenService from "../Services/WorkspaceProjectAuthTokenService";
import ObjectID from "../../Types/ObjectID";
import WorkspaceUserAuthTokenService from "../Services/WorkspaceUserAuthTokenService";
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
import MicrosoftTeamsAuthAction from "../Utils/Workspace/MicrosoftTeams/Actions/Auth";
import MicrosoftTeamsIncidentActions from "../Utils/Workspace/MicrosoftTeams/Actions/Incident";
import MicrosoftTeamsAlertActions from "../Utils/Workspace/MicrosoftTeams/Actions/Alert";
import MicrosoftTeamsScheduledMaintenanceActions from "../Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance";
import MicrosoftTeamsMonitorActions from "../Utils/Workspace/MicrosoftTeams/Actions/Monitor";
import MicrosoftTeamsOnCallDutyActions from "../Utils/Workspace/MicrosoftTeams/Actions/OnCallDutyPolicy";
import MicrosoftTeamsUtil from "../Utils/Workspace/MicrosoftTeams/MicrosoftTeams";
import archiver from "archiver";
import LocalFile from "../Utils/LocalFile";
import path from "path";
import UserMiddleware from "../Middleware/UserAuthorization";
import CommonAPI from "./CommonAPI";
export default class MicrosoftTeamsAPI {
    static getTeamsAppManifest() {
        if (!MicrosoftTeamsAppClientId) {
            throw new BadDataException("Microsoft Teams App Client ID is not set");
        }
        const manifest = {
            $schema: "https://developer.microsoft.com/json-schemas/teams/v1.23/MicrosoftTeams.schema.json",
            manifestVersion: "1.23",
            version: AppVersion.toLowerCase().includes("unknown")
                ? "1.5.0"
                : AppVersion,
            id: MicrosoftTeamsAppClientId,
            developer: {
                name: "HackerBay Inc",
                websiteUrl: "https://oneuptime.com",
                privacyUrl: "https://oneuptime.com/legal/privacy",
                termsOfUseUrl: "https://oneuptime.com/legal/terms",
            },
            publisherDocsUrl: "https://oneuptime.com/docs/workspace-connections/microsoft-teams",
            name: {
                short: "OneUptime",
                full: "OneUptime - Complete Observability Platform",
            },
            description: {
                short: "Complete open-source monitoring and observability platform. ",
                full: `<p>OneUptime is a comprehensive solution for monitoring and managing your online services. Whether you need to check the availability of your website, dashboard, API, or any other online resource, OneUptime can alert your team when downtime happens and keep your customers informed with a status page. OneUptime also helps you handle incidents, set up on-call rotations, run tests, secure your services, analyze logs, track performance, and debug errors.</p>

<p>In order to use the app, you need to have an active account with <a href="https://oneuptime.com" target="_blank">OneUptime</a>. Please send an email to <a href="mailto:support@oneuptime.com">support@oneuptime.com</a> if you need more details.</p>

<p><strong>Create a new OneUptime Account:</strong> If you wish to sign up for a new account, you can do so by visiting <a href="https://oneuptime.com" target="_blank">OneUptime Sign Up</a>.</p>

<p><strong>Help and Support:</strong> You can reach out to help and support via <a href="https://oneuptime.com/support" target="_blank">Support Page</a> or contact <a href="mailto:support@oneuptime.com">support@oneuptime.com</a>.</p>
`,
            },
            // Default to size-specific names; route will adjust if fallbacks are used
            icons: {
                outline: "outline.png",
                color: "color.png",
            },
            accentColor: "#000000",
            bots: [
                {
                    botId: MicrosoftTeamsAppClientId,
                    needsChannelSelector: false,
                    isNotificationOnly: false,
                    // Include groupChat to align with latest schema capabilities
                    scopes: ["team", "personal", "groupChat"],
                    supportsFiles: false,
                    supportsCalling: false,
                    supportsVideo: false,
                    // Provide basic command lists to improve client compatibility (esp. mobile)
                    commandLists: [
                        {
                            scopes: ["team", "groupChat", "personal"],
                            commands: [
                                {
                                    title: "help",
                                    description: "Show instructions for interacting with the OneUptime bot.",
                                },
                                {
                                    title: "create incident",
                                    description: "Launch the adaptive card to declare a new incident in OneUptime.",
                                },
                                {
                                    title: "create maintenance",
                                    description: "Open the workflow to schedule maintenance directly from Teams.",
                                },
                                {
                                    title: "show active incidents",
                                    description: "List all ongoing incidents with severity and state context.",
                                },
                                {
                                    title: "show scheduled maintenance",
                                    description: "Display upcoming scheduled maintenance events for the workspace.",
                                },
                                {
                                    title: "show ongoing maintenance",
                                    description: "Surface maintenance windows that are currently in progress.",
                                },
                                {
                                    title: "show active alerts",
                                    description: "Provide a summary of alerts that still require attention.",
                                },
                            ],
                        },
                    ],
                },
            ],
            permissions: ["identity", "messageTeamMembers"],
            authorization: {
                permissions: {
                    resourceSpecific: [
                        {
                            type: "Application",
                            name: "ChannelMessage.Send.Group",
                        },
                        {
                            type: "Application",
                            name: "ChannelMessage.Read.Group",
                        },
                        {
                            type: "Application",
                            name: "Channel.Create.Group",
                        },
                    ],
                },
            },
            validDomains: [Host],
            webApplicationInfo: {
                id: MicrosoftTeamsAppClientId,
                resource: HomeClientUrl.toString(),
            },
        };
        return manifest;
    }
    getRouter() {
        const router = Express.getRouter();
        // Teams app manifest ZIP endpoint
        router.get("/microsoft-teams/app-manifest-zip", async (req, res) => {
            try {
                // Validate GUID format – Teams requires GUID for id / botId
                const guidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
                if (!guidRegex.test(MicrosoftTeamsAppClientId || "")) {
                    return Response.sendErrorResponse(req, res, new BadDataException("Microsoft Teams App Client ID must be a valid GUID. Update the environment variable."));
                }
                // Decide icon files and names included in the package
                let iconColorName = "icon-color.png";
                let iconOutlineName = "icon-outline.png";
                // Set response headers for zip download
                res.setHeader("Content-Type", "application/zip");
                res.setHeader("Content-Disposition", 'attachment; filename="oneuptime-teams-app.zip"');
                // Create archive
                const archive = archiver("zip", {
                    zlib: { level: 9 }, // Sets the compression level
                });
                // Handle archive errors
                archive.on("error", (err) => {
                    logger.error("Archive error: " + err, getLogAttributesFromRequest(req));
                    throw err;
                });
                // Pipe archive data to the response
                archive.pipe(res);
                const colorPath = path.join(__dirname, "../Images/MicrosoftTeams/color.png");
                const outlinePath = path.join(__dirname, "../Images/MicrosoftTeams/outline.png");
                let colorIconBuffer = null;
                let outlineIconBuffer = null;
                if ((await LocalFile.doesFileExist(colorPath)) &&
                    (await LocalFile.doesFileExist(outlinePath))) {
                    colorIconBuffer = await LocalFile.readAsBuffer(colorPath);
                    outlineIconBuffer = await LocalFile.readAsBuffer(outlinePath);
                    iconColorName = "color.png";
                    iconOutlineName = "outline.png";
                }
                else {
                    throw new BadDataException("Microsoft Teams icons not found. Expected either pre-sized icon-color-192x192.png and icon-outline-32x32.png in Common/Server/Images/MicrosoftTeams, or fallback color.png and outline.png.");
                }
                // Build manifest now that icon names are known
                const manifest = MicrosoftTeamsAPI.getTeamsAppManifest();
                manifest["icons"]["color"] = iconColorName;
                manifest["icons"]["outline"] = iconOutlineName;
                // Add manifest.json to zip
                archive.append(JSON.stringify(manifest, null, 2), {
                    name: "manifest.json",
                });
                // Add icons to zip under the selected names
                archive.append(colorIconBuffer, { name: iconColorName });
                archive.append(outlineIconBuffer, { name: iconOutlineName });
                // Finalize the archive
                await archive.finalize();
            }
            catch (error) {
                logger.error("Error creating Teams app manifest zip: " + error, getLogAttributesFromRequest(req));
                return Response.sendErrorResponse(req, res, new BadDataException("Failed to create Teams app manifest zip"));
            }
        });
        /*
         * Microsoft Teams OAuth callback endpoint for project integration
         * New (preferred) static redirect URI that uses state param to carry projectId and userId
         * State format: <projectId>:<userId>
         */
        router.get("/microsoft-teams/auth", async (req, res) => {
            var _a, _b, _c, _d;
            if (!MicrosoftTeamsAppClientId) {
                return Response.sendErrorResponse(req, res, new BadDataException("Microsoft Teams App Client ID is not set"));
            }
            if (!MicrosoftTeamsAppClientSecret) {
                return Response.sendErrorResponse(req, res, new BadDataException("Microsoft Teams App Client Secret is not set"));
            }
            const error = (_a = req.query["error"]) === null || _a === void 0 ? void 0 : _a.toString();
            const stateParam = (_b = req.query["state"]) === null || _b === void 0 ? void 0 : _b.toString();
            if (!stateParam) {
                return Response.sendErrorResponse(req, res, new BadRequestException("Invalid request - state param not present"));
            }
            // Expect state in format projectId:userId
            const stateParts = stateParam.split(":");
            if (stateParts.length !== 2 || !stateParts[0] || !stateParts[1]) {
                return Response.sendErrorResponse(req, res, new BadRequestException("Invalid state param"));
            }
            const projectId = stateParts[0];
            const userId = stateParts[1];
            const teamsIntegrationPageUrl = URL.fromString(DashboardClientUrl.toString() +
                `/${projectId.toString()}/settings/microsoft-teams-integration`);
            if (error) {
                return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", error));
            }
            const code = (_c = req.query["code"]) === null || _c === void 0 ? void 0 : _c.toString();
            if (!code) {
                return Response.sendErrorResponse(req, res, new BadRequestException("Invalid request - no authorization code"));
            }
            try {
                // Exchange code for access token
                const redirectUri = URL.fromString(`${AppApiClientUrl.toString()}/microsoft-teams/auth`);
                const tokenRequestBody = {
                    grant_type: "authorization_code",
                    code: code,
                    client_id: MicrosoftTeamsAppClientId,
                    client_secret: MicrosoftTeamsAppClientSecret,
                    redirect_uri: redirectUri.toString(),
                    scope: "https://graph.microsoft.com/User.Read https://graph.microsoft.com/Team.ReadBasic.All https://graph.microsoft.com/Channel.ReadBasic.All https://graph.microsoft.com/ChannelMessage.Send",
                };
                logger.debug("Microsoft Teams Token Request Body (static redirect): ", getLogAttributesFromRequest(req));
                logger.debug(tokenRequestBody, getLogAttributesFromRequest(req));
                const tokenResponse = await API.post({
                    url: URL.fromString("https://login.microsoftonline.com/common/oauth2/v2.0/token"),
                    data: tokenRequestBody,
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded",
                    },
                });
                if (tokenResponse instanceof HTTPErrorResponse) {
                    logger.error("Error getting Teams token:", getLogAttributesFromRequest(req));
                    logger.error(tokenResponse, getLogAttributesFromRequest(req));
                    throw tokenResponse;
                }
                const tokenData = tokenResponse.data;
                logger.debug("Microsoft Teams Token Response (static redirect): ", getLogAttributesFromRequest(req));
                logger.debug(tokenData, getLogAttributesFromRequest(req));
                if (!tokenData["access_token"]) {
                    return Response.sendErrorResponse(req, res, new BadRequestException("Failed to get access token from Microsoft Teams"));
                }
                const accessToken = tokenData["access_token"];
                // Get user profile and team information
                const userProfileResponse = await API.get({
                    url: URL.fromString("https://graph.microsoft.com/v1.0/me"),
                    headers: {
                        Authorization: `Bearer ${accessToken}`,
                    },
                });
                if (userProfileResponse instanceof HTTPErrorResponse) {
                    logger.error("Error getting user profile:", getLogAttributesFromRequest(req));
                    logger.error(userProfileResponse, getLogAttributesFromRequest(req));
                    throw userProfileResponse;
                }
                const userProfile = userProfileResponse.data;
                logger.debug("User Profile: ", getLogAttributesFromRequest(req));
                logger.debug(userProfile, getLogAttributesFromRequest(req));
                await WorkspaceUserAuthTokenService.refreshAuthToken({
                    projectId: new ObjectID(projectId),
                    userId: new ObjectID(userId),
                    workspaceType: WorkspaceType.MicrosoftTeams,
                    authToken: accessToken,
                    workspaceUserId: userProfile["id"],
                    miscData: {
                        userId: userProfile["id"],
                        displayName: userProfile["displayName"],
                        email: userProfile["mail"] ||
                            userProfile["userPrincipalName"],
                    },
                });
                // Check if admin consent is already granted
                const existingProjectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
                    projectId: new ObjectID(projectId),
                    workspaceType: WorkspaceType.MicrosoftTeams,
                });
                if (existingProjectAuth &&
                    ((_d = existingProjectAuth.miscData) === null || _d === void 0 ? void 0 : _d.adminConsentGranted)) {
                    // Admin consent already granted, refresh teams
                    await MicrosoftTeamsUtil.refreshTeams({
                        projectId: new ObjectID(projectId),
                    });
                    return Response.redirect(req, res, teamsIntegrationPageUrl);
                }
                // Need admin consent
                return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("needAdminConsent", "true"));
            }
            catch (err) {
                logger.error("Error in static Microsoft Teams auth callback: ", getLogAttributesFromRequest(req));
                logger.error(err, getLogAttributesFromRequest(req));
                return Response.sendErrorResponse(req, res, new BadDataException("Failed to authenticate with Microsoft Teams"));
            }
        });
        /*
         * Admin consent - start flow (tenant-wide admin consent)
         * Uses state in the same format as OAuth: <projectId>:<userId>
         */
        router.get("/microsoft-teams/admin-consent", async (req, res) => {
            var _a;
            try {
                if (!MicrosoftTeamsAppClientId) {
                    return Response.sendErrorResponse(req, res, new BadDataException("Microsoft Teams App Client ID is not set"));
                }
                const stateParam = (_a = req.query["state"]) === null || _a === void 0 ? void 0 : _a.toString();
                if (!stateParam) {
                    return Response.sendErrorResponse(req, res, new BadRequestException("Invalid request - state param not present"));
                }
                const stateParts = stateParam.split(":");
                if (stateParts.length !== 2 || !stateParts[0] || !stateParts[1]) {
                    return Response.sendErrorResponse(req, res, new BadRequestException("Invalid state param"));
                }
                const projectId = stateParts[0];
                // Try to use tenant from existing project auth, otherwise default to "organizations"
                let tenantForConsent = "organizations";
                try {
                    const existingAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
                        projectId: new ObjectID(projectId),
                        workspaceType: WorkspaceType.MicrosoftTeams,
                    });
                    const existingTenant = existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.workspaceProjectId;
                    if (existingTenant) {
                        tenantForConsent = existingTenant;
                    }
                }
                catch (_b) {
                    // ignore and fall back to default
                }
                const redirectUri = URL.fromString(`${AppApiClientUrl.toString()}/microsoft-teams/admin-consent/callback`);
                const adminConsentUrl = `https://login.microsoftonline.com/${encodeURIComponent(tenantForConsent)}/v2.0/adminconsent?client_id=${encodeURIComponent(MicrosoftTeamsAppClientId)}&scope=${encodeURIComponent("https://graph.microsoft.com/.default")}&redirect_uri=${encodeURIComponent(redirectUri.toString())}&state=${encodeURIComponent(stateParam)}`;
                return Response.redirect(req, res, URL.fromString(adminConsentUrl));
            }
            catch (error) {
                logger.error("Error starting Teams admin consent: ", getLogAttributesFromRequest(req));
                logger.error(error, getLogAttributesFromRequest(req));
                return Response.sendErrorResponse(req, res, new BadDataException("Failed to start Microsoft Teams admin consent"));
            }
        });
        /*
         * Admin consent - callback handler
         * Receives: state=<projectId>:<userId>, tenant=<tenantId>, admin_consent=True | error params
         */
        router.get("/microsoft-teams/admin-consent/callback", async (req, res) => {
            var _a, _b, _c, _d, _e;
            try {
                const error = (_a = req.query["error"]) === null || _a === void 0 ? void 0 : _a.toString();
                const errorDescription = (_b = req.query["error_description"]) === null || _b === void 0 ? void 0 : _b.toString();
                const stateParam = (_c = req.query["state"]) === null || _c === void 0 ? void 0 : _c.toString();
                const tenantId = (_d = req.query["tenant"]) === null || _d === void 0 ? void 0 : _d.toString();
                if (!stateParam) {
                    return Response.sendErrorResponse(req, res, new BadRequestException("Invalid request - state param not present"));
                }
                const stateParts = stateParam.split(":");
                if (stateParts.length !== 2 || !stateParts[0] || !stateParts[1]) {
                    return Response.sendErrorResponse(req, res, new BadRequestException("Invalid state param"));
                }
                const projectId = stateParts[0];
                const teamsIntegrationPageUrl = URL.fromString(DashboardClientUrl.toString() +
                    `/${projectId.toString()}/settings/microsoft-teams-integration`);
                if (error) {
                    return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", `${error}${errorDescription ? ": " + errorDescription : ""}`));
                }
                if (!tenantId) {
                    return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", "Missing tenant information from admin consent callback"));
                }
                if (!MicrosoftTeamsAppClientId || !MicrosoftTeamsAppClientSecret) {
                    return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", "Microsoft Teams App credentials are not configured"));
                }
                // Fetch any existing project auth to merge
                const existingAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
                    projectId: new ObjectID(projectId),
                    workspaceType: WorkspaceType.MicrosoftTeams,
                });
                // Acquire an application token for the specific tenant using client credentials
                const tokenResp = await API.post({
                    url: URL.fromString(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`),
                    data: {
                        client_id: MicrosoftTeamsAppClientId,
                        client_secret: MicrosoftTeamsAppClientSecret,
                        grant_type: "client_credentials",
                        scope: "https://graph.microsoft.com/.default",
                    },
                    headers: { "Content-Type": "application/x-www-form-urlencoded" },
                });
                if (tokenResp instanceof HTTPErrorResponse) {
                    logger.error("Error getting app token after admin consent:", getLogAttributesFromRequest(req));
                    logger.error(tokenResp, getLogAttributesFromRequest(req));
                    return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", "Failed to get Graph app token after admin consent"));
                }
                const tokenData = tokenResp.data;
                const appAccessToken = tokenData["access_token"] || "";
                const expiresInSec = Number(tokenData["expires_in"] || 0);
                const expiresAtIso = new Date(Date.now() + Math.max(0, (expiresInSec - 60) * 1000)).toISOString();
                logger.debug("App Access Token acquired via admin consent: ", getLogAttributesFromRequest(req));
                logger.debug(tokenData, getLogAttributesFromRequest(req));
                // Get available teams from user auth token
                const userId = stateParts[1];
                const userAuth = await WorkspaceUserAuthTokenService.getUserAuth({
                    projectId: new ObjectID(projectId),
                    userId: new ObjectID(userId),
                    workspaceType: WorkspaceType.MicrosoftTeams,
                });
                let availableTeams = {};
                if (userAuth === null || userAuth === void 0 ? void 0 : userAuth.miscData) {
                    availableTeams = userAuth.miscData.availableTeams || {};
                }
                // If no teams from user auth, try to get them using app token
                if (Object.keys(availableTeams).length === 0) {
                    try {
                        const teamsResponse = await API.get({
                            url: URL.fromString("https://graph.microsoft.com/v1.0/teams?$select=id,displayName"),
                            headers: {
                                Authorization: `Bearer ${appAccessToken}`,
                            },
                        });
                        if (teamsResponse instanceof HTTPErrorResponse) {
                            logger.error("Failed to get teams:", getLogAttributesFromRequest(req));
                            logger.error(teamsResponse, getLogAttributesFromRequest(req));
                            return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", "Failed to retrieve teams from Microsoft Graph API after admin consent"));
                        }
                        const teamsData = teamsResponse.data;
                        const teams = teamsData["value"] || [];
                        if (teams.length === 0) {
                            return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", "No teams available in your Microsoft 365 tenant. Please create a team first."));
                        }
                        availableTeams = teams.reduce((acc, t) => {
                            const team = {
                                id: t["id"],
                                name: t["displayName"] || "Unnamed Team",
                            };
                            acc[team.name] = team;
                            return acc;
                        }, {});
                    }
                    catch (error) {
                        logger.error("Error getting teams:", getLogAttributesFromRequest(req));
                        logger.error(error, getLogAttributesFromRequest(req));
                        return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", "Failed to retrieve teams from Microsoft Graph API"));
                    }
                }
                // Merge and persist project auth with tenantId, app token, and available teams
                const mergedMiscData = Object.assign(Object.assign({}, existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.miscData), { tenantId: tenantId, appAccessToken: appAccessToken, appAccessTokenExpiresAt: expiresAtIso, adminConsentGranted: true, adminConsentGrantedAt: new Date().toISOString(), availableTeams: availableTeams, botId: MicrosoftTeamsAppClientId || "" });
                await WorkspaceProjectAuthTokenService.refreshAuthToken({
                    projectId: new ObjectID(projectId),
                    workspaceType: WorkspaceType.MicrosoftTeams,
                    authToken: appAccessToken,
                    workspaceProjectId: tenantId, // Use tenant ID as the workspace project identifier
                    miscData: mergedMiscData,
                });
                return Response.redirect(req, res, teamsIntegrationPageUrl
                    .addQueryParam("adminConsent", "success")
                    .addQueryParam("tenantId", tenantId));
            }
            catch (err) {
                logger.error("Error in Microsoft Teams admin consent callback: ", getLogAttributesFromRequest(req));
                logger.error(err, getLogAttributesFromRequest(req));
                // Best-effort redirect to integration page with error
                try {
                    const stateParam = (_e = req.query["state"]) === null || _e === void 0 ? void 0 : _e.toString();
                    const projectId = stateParam === null || stateParam === void 0 ? void 0 : stateParam.split(":")[0];
                    if (projectId) {
                        const teamsIntegrationPageUrl = URL.fromString(DashboardClientUrl.toString() +
                            `/${projectId.toString()}/settings/microsoft-teams-integration`);
                        return Response.redirect(req, res, teamsIntegrationPageUrl.addQueryParam("error", "Failed to finalize Microsoft Teams admin consent"));
                    }
                }
                catch (_f) {
                    // ignore
                }
                return Response.sendErrorResponse(req, res, new BadDataException("Failed to finalize Microsoft Teams admin consent"));
            }
        });
        /*
         * Microsoft Bot Framework endpoint - this is what Teams calls for bot messages
         * Now uses the Bot Framework SDK's adapter.processActivity for proper protocol handling
         */
        router.post("/microsoft-bot/messages", async (req, res) => {
            try {
                // Delegate to MicrosoftTeamsUtil which uses the Bot Framework SDK
                await MicrosoftTeamsUtil.processBotActivity(req, res);
            }
            catch (error) {
                logger.error("Error in Bot Framework endpoint: " + error, getLogAttributesFromRequest(req));
                if (!res.headersSent) {
                    Response.sendJsonObjectResponse(req, res, {
                        error: "Internal server error",
                    });
                }
            }
        });
        // Microsoft Teams webhook endpoint for interactive messages (legacy)
        router.post("/microsoft-teams/webhook", async (req, res) => {
            logger.debug("Microsoft Teams Webhook Request: ", getLogAttributesFromRequest(req));
            logger.debug(req.body, getLogAttributesFromRequest(req));
            try {
                const authResult = await MicrosoftTeamsAuthAction.isAuthorized({
                    req: req,
                });
                logger.debug("Microsoft Teams Auth Result: ", getLogAttributesFromRequest(req));
                logger.debug(authResult, getLogAttributesFromRequest(req));
                if (authResult.isAuthorized === false) {
                    return Response.sendTextResponse(req, res, "");
                }
                // Handle different types of Teams activities
                const activity = req.body;
                const activityType = activity["type"];
                if (activityType === "message") {
                    // Handle bot mentions or direct messages
                    return MicrosoftTeamsAPI.handleMessageActivity(req, res, authResult, activity);
                }
                else if (activityType === "invoke") {
                    // Handle adaptive card actions
                    return MicrosoftTeamsAPI.handleInvokeActivity(req, res, authResult, activity);
                }
                return Response.sendTextResponse(req, res, "");
            }
            catch (error) {
                logger.error("Error processing Teams webhook:", getLogAttributesFromRequest(req));
                logger.error(error, getLogAttributesFromRequest(req));
                return Response.sendTextResponse(req, res, "");
            }
        });
        // Test endpoint to verify Bot Framework setup
        router.get("/microsoft-bot/test", async (req, res) => {
            if (!MicrosoftTeamsAppClientId) {
                return Response.sendJsonObjectResponse(req, res, {
                    error: "Microsoft Teams App Client ID not configured",
                });
            }
            if (!MicrosoftTeamsAppClientSecret) {
                return Response.sendJsonObjectResponse(req, res, {
                    error: "Microsoft Teams App Client Secret not configured",
                });
            }
            return Response.sendJsonObjectResponse(req, res, {
                status: "Bot Framework endpoint is configured",
                clientId: MicrosoftTeamsAppClientId,
                messagingEndpoint: `${AppApiClientUrl.toString()}/microsoft-bot/messages`,
            });
        });
        // Connector configuration endpoint
        router.get("/microsoft-teams/connector-config", (_req, res) => {
            // This endpoint provides configuration UI for Teams connectors
            const html = `
<!DOCTYPE html>
<html>
<head>
    <title>OneUptime Teams Connector</title>
    <script src="https://statics.teams.cdn.office.net/sdk/v1.11.0/js/MicrosoftTeams.min.js"></script>
</head>
<body>
    <h1>OneUptime Teams Connector Setup</h1>
    <p>Configure OneUptime notifications for your team.</p>
    <button onclick="saveConfiguration()">Save Configuration</button>

    <script>
        microsoftTeams.initialize();

        function saveConfiguration() {
            microsoftTeams.settings.setSettings({
                entityId: "oneuptime-connector",
                contentUrl: "https://oneuptime.com",
                suggestedDisplayName: "OneUptime Notifications"
            });
            microsoftTeams.settings.setValidityState(true);
        }

        microsoftTeams.settings.registerOnSaveHandler((saveEvent) => {
            // Handle save configuration
            saveEvent.notifySuccess();
        });
    </script>
</body>
</html>`;
            res.setHeader("Content-Type", "text/html");
            return res.send(html);
        });
        // Get available teams for a project
        router.get("/microsoft-teams/teams", UserMiddleware.getUserMiddleware, async (req, res) => {
            try {
                const databaseProps = await CommonAPI.getDatabaseCommonInteractionProps(req);
                const projectId = databaseProps.tenantId;
                // Use the refreshTeams method to get fresh teams data
                const availableTeams = await MicrosoftTeamsUtil.refreshTeams(Object.assign({ projectId: projectId }, (databaseProps.userId && { userId: databaseProps.userId })));
                return Response.sendJsonObjectResponse(req, res, {
                    teams: Object.values(availableTeams).map((team) => {
                        return {
                            id: team.id,
                            name: team.name,
                        };
                    }),
                });
            }
            catch (err) {
                return Response.sendErrorResponse(req, res, err);
            }
        });
        // Endpoint to refresh teams list
        router.post("/microsoft-teams/refresh-teams", UserMiddleware.getUserMiddleware, async (req, res) => {
            try {
                const databaseProps = await CommonAPI.getDatabaseCommonInteractionProps(req);
                const projectId = databaseProps.tenantId;
                // Call MicrosoftTeamsUtil to refresh teams
                const availableTeams = await MicrosoftTeamsUtil.refreshTeams(Object.assign({ projectId: projectId }, (databaseProps.userId && { userId: databaseProps.userId })));
                return Response.sendJsonObjectResponse(req, res, {
                    teams: Object.values(availableTeams).map((team) => {
                        return {
                            id: team.id,
                            name: team.name,
                        };
                    }),
                });
            }
            catch (err) {
                return Response.sendErrorResponse(req, res, err);
            }
        });
        return router;
    }
    static async handleMessageActivity(_req, res, authResult, activity) {
        // Handle direct messages to bot or @mentions
        const messageText = activity["text"] || "";
        const from = activity["from"];
        if (messageText.toLowerCase().includes("help")) {
            // Send help message
            const helpMessage = {
                _type: "WorkspacePayloadText",
                text: "Hello! I'm the OneUptime bot. I can help you:\n\n• Get notifications about incidents\n• Acknowledge alerts\n• View system status\n\nType 'status' to see current system status.",
            };
            await MicrosoftTeamsUtil.sendDirectMessageToUser({
                authToken: authResult.authToken,
                workspaceUserId: from["id"],
                messageBlocks: [helpMessage],
            });
        }
        Response.sendTextResponse(_req, res, "");
    }
    static async handleInvokeActivity(req, res, authResult, _activity) {
        /*
         * Handle adaptive card button clicks
         * const value: JSONObject = activity["value"] as JSONObject;
         * const actionType: string = value["action"] as string;
         */
        for (const action of authResult.actions || []) {
            if (!action.actionType) {
                continue;
            }
            if (MicrosoftTeamsIncidentActions.isIncidentAction({
                actionType: action.actionType,
            })) {
                return MicrosoftTeamsIncidentActions.handleIncidentAction({
                    teamsRequest: authResult,
                    action: action,
                    req: req,
                    res: res,
                });
            }
            if (MicrosoftTeamsAlertActions.isAlertAction({
                actionType: action.actionType,
            })) {
                return MicrosoftTeamsAlertActions.handleAlertAction({
                    teamsRequest: authResult,
                    action: action,
                    req: req,
                    res: res,
                });
            }
            if (MicrosoftTeamsScheduledMaintenanceActions.isScheduledMaintenanceAction({
                actionType: action.actionType,
            })) {
                return MicrosoftTeamsScheduledMaintenanceActions.handleScheduledMaintenanceAction({
                    teamsRequest: authResult,
                    action: action,
                    req: req,
                    res: res,
                });
            }
            if (MicrosoftTeamsMonitorActions.isMonitorAction({
                actionType: action.actionType,
            })) {
                return MicrosoftTeamsMonitorActions.handleMonitorAction({
                    teamsRequest: authResult,
                    action: action,
                    req: req,
                    res: res,
                });
            }
            if (MicrosoftTeamsOnCallDutyActions.isOnCallDutyAction({
                actionType: action.actionType,
            })) {
                return MicrosoftTeamsOnCallDutyActions.handleOnCallDutyAction({
                    teamsRequest: authResult,
                    action: action,
                    req: req,
                    res: res,
                });
            }
        }
        Response.sendTextResponse(req, res, "");
    }
}
//# sourceMappingURL=MicrosoftTeamsAPI.js.map