import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import { chromium } from "playwright";
import { GoogleCalendarClient } from "../../calendar/google-calendar.js";
import { GmailEmailClient } from "../../email/gmail-email.js";
import { GoogleDriveClient } from "../../drive/google-drive.js";
import { hasLocalGoogleRefreshToken } from "../../google/token-file.js";
import { ensureBrowser, getCdpEndpoint } from "../../agent/browser-launcher.js";
import { createGuestCalendarClient, loadE2EGuestTokens } from "../setup-google-guest.js";
import { buildSuiteResult, ok, runTest, skipped } from "../suite-utils.js";
function guestEmail(context) {
    return context.config.e2e?.google?.meetGuestEmail ?? process.env.E2E_GOOGLE_MEET_GUEST_EMAIL;
}
export const googleSuite = {
    id: "google",
    name: "Google Workspace",
    run: async (context) => {
        const started = Date.now();
        const full = context.mode === "smoke" || context.mode === "google";
        const marker = `VisionClaw E2E ${context.runId}`;
        const tests = [];
        if (!hasLocalGoogleRefreshToken()) {
            tests.push(await runTest("google", "google.auth", "Google auth", () => Promise.resolve(skipped("Google tokens missing"))));
            return buildSuiteResult("google", "Google Workspace", started, tests);
        }
        tests.push(await runTest("google", "google.gmail.list", "Gmail list", async () => {
            const client = new GmailEmailClient(context.config);
            const emails = await client.listEmails({ maxResults: 1 });
            return ok(`Listed ${emails.length} email(s)`);
        }));
        tests.push(await runTest("google", "google.calendar.list", "Calendar list", async () => {
            const client = new GoogleCalendarClient(context.config);
            const now = new Date();
            const events = await client.listUpcomingEvents(now, new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000), 5);
            return ok(`Listed ${events.length} event(s)`);
        }));
        tests.push(await runTest("google", "google.drive.list", "Drive list", async () => {
            const client = new GoogleDriveClient(context.config);
            const files = await client.listFiles({ maxResults: 5 });
            return ok(`Listed ${files.length} file(s)`);
        }));
        if (full) {
            let messageId;
            tests.push(await runTest("google", "google.gmail.send_search_read", "Gmail send/search/read", async () => {
                const client = new GmailEmailClient(context.config);
                const sent = await client.sendEmail({
                    to: context.config.gmail,
                    subject: marker,
                    body: `${marker}\nPlease ignore.`,
                });
                messageId = sent.id;
                if (!messageId)
                    throw new Error("Send did not return message id");
                context.addCleanupItem({ type: "gmail_message", id: messageId, suite: "google" });
                const found = await client.listEmails({ query: `subject:"${marker}"`, maxResults: 5 });
                if (found.length === 0)
                    throw new Error("Sent email not found");
                const detail = await client.getEmail(found[0].id);
                if (!detail.bodyText?.includes(marker))
                    throw new Error("Email body mismatch");
                return ok("Gmail roundtrip succeeded");
            }));
            let eventId;
            let hangoutLink;
            tests.push(await runTest("google", "google.calendar.create_update_delete", "Calendar CRUD", async () => {
                const client = new GoogleCalendarClient(context.config);
                const start = new Date(Date.now() + 10 * 60 * 1000);
                const end = new Date(start.getTime() + 15 * 60 * 1000);
                const created = await client.createEvent({
                    summary: marker,
                    description: marker,
                    start,
                    end,
                });
                eventId = created.id ?? undefined;
                if (!eventId)
                    throw new Error("Calendar event id missing");
                context.addCleanupItem({ type: "calendar_event", id: eventId, suite: "google" });
                await client.updateEvent(eventId, { summary: `${marker} updated` });
                return ok("Calendar create/update succeeded", { eventId });
            }));
            tests.push(await runTest("google", "google.calendar.guest_can_see_event", "Guest can see meeting", async () => {
                const email = guestEmail(context);
                if (!email)
                    return skipped("Guest email not configured");
                if (!loadE2EGuestTokens())
                    return skipped("Guest OAuth token missing; run e2e setup google-guest");
                const owner = new GoogleCalendarClient(context.config);
                const start = new Date(Date.now() + 20 * 60 * 1000);
                const end = new Date(start.getTime() + 15 * 60 * 1000);
                const created = await owner.createEvent({
                    summary: `${marker} Meeting`,
                    description: marker,
                    start,
                    end,
                    attendees: [email],
                });
                eventId = created.id ?? eventId;
                hangoutLink = created.hangoutLink ?? undefined;
                if (eventId)
                    context.addCleanupItem({ type: "calendar_event", id: eventId, suite: "google" });
                if (!hangoutLink)
                    throw new Error("Meet link not generated");
                const guestCalendar = createGuestCalendarClient(context.config);
                if (!guestCalendar)
                    return skipped("Guest calendar client unavailable");
                let guestEvents = [];
                for (let attempt = 0; attempt < 5; attempt++) {
                    await new Promise((resolve) => setTimeout(resolve, 3000));
                    const res = await guestCalendar.events.list({
                        calendarId: "primary",
                        timeMin: start.toISOString(),
                        timeMax: new Date(end.getTime() + 60 * 60 * 1000).toISOString(),
                        q: marker,
                        singleEvents: true,
                    });
                    guestEvents = res.data.items ?? [];
                    if (guestEvents.length > 0)
                        break;
                }
                if (guestEvents.length === 0)
                    throw new Error("Guest cannot see invited event");
                return ok("Guest can see invited event", { eventId, hasMeetLink: !!hangoutLink });
            }));
            tests.push(await runTest("google", "google.meet.guest_can_open_join_page", "Guest Meet page", async () => {
                if (!hangoutLink)
                    return skipped("Meet link unavailable from previous test");
                await ensureBrowser();
                const browser = await chromium.connectOverCDP(getCdpEndpoint());
                const ctx = await browser.newContext();
                try {
                    const page = await ctx.newPage();
                    await page.goto(hangoutLink, { waitUntil: "domcontentloaded", timeout: 15000 });
                    const url = page.url();
                    if (url.includes("error") || url.includes("lookup"))
                        throw new Error(`Meet link redirected to error page: ${url}`);
                    const screenshotPath = path.join(context.artifactsDir, "meet-join-page.png");
                    await page.screenshot({ path: screenshotPath });
                    return ok("Meet join page loaded", { url, screenshotPath });
                }
                finally {
                    await ctx.close();
                }
            }));
            tests.push(await runTest("google", "google.drive.crud", "Drive CRUD", async () => {
                const client = new GoogleDriveClient(context.config);
                const folder = await client.createFolder({ name: marker });
                const tmpFile = path.join(os.tmpdir(), `${context.runId}.txt`);
                fs.writeFileSync(tmpFile, marker, "utf-8");
                context.addCleanupItem({ type: "local_file", id: tmpFile, suite: "google" });
                context.addCleanupItem({ type: "drive_file", id: folder.id, suite: "google", details: { role: "folder" } });
                const uploaded = await client.uploadFile({ localPath: tmpFile, folderId: folder.id, name: `${marker}.txt` });
                context.addCleanupItem({ type: "drive_file", id: uploaded.id, suite: "google", details: { role: "file" } });
                const listed = await client.listFiles({ query: `name contains '${marker}'` });
                if (listed.length === 0)
                    throw new Error("Uploaded file not found");
                return ok("Drive CRUD succeeded");
            }));
        }
        return buildSuiteResult("google", "Google Workspace", started, tests);
    },
};
//# sourceMappingURL=google.js.map