import nock from "nock";
import yargs from "yargs/yargs";
import customDomainCommand from "../../cmds/custom-domain/index.js";
import { cleanupTest, RequestCapture, setupAuthenticatedNock, setupTestEnvironment, TEST_ACCOUNT_NAME, TEST_API_BASE, TEST_AUTH_TOKEN, } from "./test-utils.js";
async function executeCustomDomainCommand(subcommand, args) {
    const yargsInstance = yargs([])
        .command(customDomainCommand)
        .help(false)
        .version(false)
        .exitProcess(false);
    const commandArgs = ["custom-domain", subcommand];
    if (args.account) {
        commandArgs.push("--account", args.account);
    }
    if (args["api-key"]) {
        commandArgs.push("--api-key", args["api-key"]);
    }
    if (args.hostname) {
        commandArgs.push("--hostname", args.hostname);
    }
    if (args["deployment-name"]) {
        commandArgs.push("--deployment-name", args["deployment-name"]);
    }
    if (args["custom-domain-type"]) {
        commandArgs.push("--custom-domain-type", args["custom-domain-type"]);
    }
    if (args.output) {
        commandArgs.push("--output", args.output);
    }
    return await yargsInstance.parse(commandArgs);
}
const mockPrintResult = jest.mocked(require("../../common/output.js").printResultToConsoleAndExitGracefully);
const mockPrintTable = jest.mocked(require("../../common/output.js").printTableToConsoleAndExitGracefully);
const mockPrintJson = jest.mocked(require("../../common/output.js").printJsonToConsoleAndExitGracefully);
const mockPrintDiagnostics = jest.mocked(require("../../common/output.js").printDiagnosticsToConsole);
const mockPrintCriticalFailure = jest.mocked(require("../../common/output.js").printCriticalFailureToConsoleAndExit);
describe("Custom Domain Command Integration Tests", () => {
    let requestCapture;
    beforeEach(() => {
        setupTestEnvironment();
        requestCapture = new RequestCapture();
        nock.disableNetConnect();
        jest.clearAllMocks();
        jest.spyOn(process, "exit").mockImplementation((() => {
            throw new Error("Process would exit");
        }));
    });
    afterEach(() => {
        cleanupTest();
        requestCapture.clear();
    });
    describe("Custom Domain List Command", () => {
        it("should intercept GET request to list custom domains", async () => {
            const mockResponse = {
                data: [
                    {
                        id: "cd_1",
                        accountName: TEST_ACCOUNT_NAME,
                        projectName: "project-a",
                        hostname: "api.example.com",
                        provider: "cloudflare",
                        deployments: [
                            {
                                deploymentName: "deployment-a",
                                branch: "main",
                                environmentType: "PRODUCTION",
                                isDefault: true,
                                stage: "api",
                                cname: "cname.zuplo.api",
                            },
                        ],
                    },
                    {
                        id: "cd_2",
                        accountName: TEST_ACCOUNT_NAME,
                        projectName: "",
                        hostname: "orphan.example.com",
                        provider: "alias",
                        deployments: [],
                    },
                ],
                offset: 0,
                limit: 100,
            };
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .get(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, mockResponse);
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await executeCustomDomainCommand("list", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintTable).toHaveBeenCalledWith([
                {
                    hostname: "api.example.com",
                    provider: "cloudflare",
                    "project-name": "project-a",
                    "deployment-name": "deployment-a",
                    branch: "main",
                    "environment-type": "PRODUCTION",
                    stage: "api",
                    "is-default": true,
                    cname: "cname.zuplo.api",
                },
                {
                    hostname: "orphan.example.com",
                    provider: "alias",
                    "project-name": "",
                    "deployment-name": "",
                    branch: "",
                    "environment-type": "",
                    stage: "",
                    "is-default": "",
                    cname: "",
                },
            ]);
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-list-requests");
        });
        it("should output flattened rows as JSON when requested", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .get(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                data: [
                    {
                        id: "cd_1",
                        accountName: TEST_ACCOUNT_NAME,
                        projectName: "project-a",
                        hostname: "api.example.com",
                        provider: "cloudflare",
                        deployments: [
                            {
                                deploymentName: "deployment-a",
                                branch: "main",
                                environmentType: "PRODUCTION",
                                isDefault: true,
                                stage: "api",
                                cname: "cname.zuplo.api",
                            },
                        ],
                    },
                ],
                offset: 0,
                limit: 100,
            });
            await executeCustomDomainCommand("list", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                output: "json",
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintJson).toHaveBeenCalledWith([
                {
                    hostname: "api.example.com",
                    provider: "cloudflare",
                    projectName: "project-a",
                    deploymentName: "deployment-a",
                    branch: "main",
                    environmentType: "PRODUCTION",
                    stage: "api",
                    isDefault: true,
                    cname: "cname.zuplo.api",
                },
            ]);
        });
        it("should handle empty custom domains list", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .get(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                data: [],
                offset: 0,
                limit: 100,
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await executeCustomDomainCommand("list", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintResult).toHaveBeenCalledWith("No custom domains found");
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-list-empty-requests");
        });
        it("should handle API error responses", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .get(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(403, {
                error: "Forbidden",
                message: "Access denied",
                statusCode: 403,
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await expect(executeCustomDomainCommand("list", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
            })).rejects.toThrow("Failed to list custom domains for account");
            expect(scope.isDone()).toBe(true);
            expect(mockPrintDiagnostics).toHaveBeenCalledWith("Error: Failed to list custom domains for your account. Try again later.", {
                error: "Forbidden",
                message: "Access denied",
                statusCode: 403,
            });
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-list-error-requests");
        });
    });
    describe("Custom Domain Create Command", () => {
        it("should intercept POST request to create custom domain", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .post(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                hostname: "api.example.com",
                deploymentName: "deployment-a",
                stage: "api",
                cname: "cname.zuplo.api",
                ownershipVerification: {
                    name: "_acme-challenge.api.example.com",
                    type: "TXT",
                    value: "verification-token",
                },
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await executeCustomDomainCommand("create", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
                "deployment-name": "deployment-a",
                "custom-domain-type": "api",
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintTable).toHaveBeenCalledWith({
                hostname: "api.example.com",
                "deployment-name": "deployment-a",
                stage: "api",
                cname: "cname.zuplo.api",
                "ownership-verification-name": "_acme-challenge.api.example.com",
                "ownership-verification-type": "TXT",
                "ownership-verification-value": "verification-token",
            });
            const capturedRequests = requestCapture.getRequests();
            expect(capturedRequests).toMatchSnapshot("custom-domain-create-requests");
            expect(capturedRequests[0].body).toEqual({
                hostname: "api.example.com",
                deploymentName: "deployment-a",
                stage: "api",
            });
        });
        it("should output the mutation result as JSON when requested", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .post(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                hostname: "api.example.com",
                deploymentName: "deployment-a",
                stage: "api",
                cname: "cname.zuplo.api",
                ownershipVerification: {
                    name: "_acme-challenge.api.example.com",
                    type: "TXT",
                    value: "verification-token",
                },
            });
            await executeCustomDomainCommand("create", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
                "deployment-name": "deployment-a",
                output: "json",
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintJson).toHaveBeenCalledWith({
                hostname: "api.example.com",
                deploymentName: "deployment-a",
                stage: "api",
                cname: "cname.zuplo.api",
                ownershipVerification: {
                    name: "_acme-challenge.api.example.com",
                    type: "TXT",
                    value: "verification-token",
                },
            });
        });
        it("should handle custom domain creation error", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .post(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(400, {
                title: "Bad Request",
                detail: "Invalid hostname",
                status: 400,
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await expect(executeCustomDomainCommand("create", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "https://bad.example.com",
            })).rejects.toThrow("Failed to create custom domain for account");
            expect(scope.isDone()).toBe(true);
            expect(mockPrintDiagnostics).toHaveBeenCalledWith("Error: Failed to create custom domain for your account. Check the arguments.", {
                title: "Bad Request",
                detail: "Invalid hostname",
                status: 400,
            });
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-create-error-requests");
        });
    });
    describe("Custom Domain Update Command", () => {
        it("should intercept PATCH request to reassign a custom domain", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .patch(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                hostname: "api.example.com",
                deploymentName: "deployment-b",
                stage: "api",
                cname: "cname.zuplo.api",
                ownershipVerification: null,
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await executeCustomDomainCommand("update", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
                "deployment-name": "deployment-b",
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintTable).toHaveBeenCalledWith({
                hostname: "api.example.com",
                "deployment-name": "deployment-b",
                stage: "api",
                cname: "cname.zuplo.api",
                "ownership-verification-name": "",
                "ownership-verification-type": "",
                "ownership-verification-value": "",
            });
            const capturedRequests = requestCapture.getRequests();
            expect(capturedRequests).toMatchSnapshot("custom-domain-update-requests");
            expect(capturedRequests[0].body).toEqual({
                hostname: "api.example.com",
                deploymentName: "deployment-b",
            });
        });
        it("should send hostname only when detaching", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .patch(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                hostname: "api.example.com",
                deploymentName: null,
                stage: "api",
                cname: "cname.zuplo.api",
                ownershipVerification: null,
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await executeCustomDomainCommand("update", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
            });
            expect(scope.isDone()).toBe(true);
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-update-detach-requests");
            expect(requestCapture.getRequests()[0].body).toEqual({
                hostname: "api.example.com",
            });
        });
        it("should handle update API errors", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .patch(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(404, {
                title: "Not Found",
                detail: "The custom domain was not found on this account",
                status: 404,
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await expect(executeCustomDomainCommand("update", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "missing.example.com",
            })).rejects.toThrow("Failed to update custom domain for account");
            expect(scope.isDone()).toBe(true);
            expect(mockPrintDiagnostics).toHaveBeenCalledWith("Error: Failed to update custom domain for your account. Check the arguments.", {
                title: "Not Found",
                detail: "The custom domain was not found on this account",
                status: 404,
            });
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-update-error-requests");
        });
    });
    describe("Custom Domain Delete Command", () => {
        it("should intercept DELETE request with explicit deployment name", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .delete(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains?hostname=api.example.com&deploymentName=deployment-a`)
                .reply(204);
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await executeCustomDomainCommand("delete", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
                "deployment-name": "deployment-a",
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintResult).toHaveBeenCalledWith("Custom domain api.example.com deleted successfully.");
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-delete-requests");
        });
        it("should output JSON for delete when requested", async () => {
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .delete(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains?hostname=api.example.com&deploymentName=deployment-a`)
                .reply(204);
            await executeCustomDomainCommand("delete", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
                "deployment-name": "deployment-a",
                output: "json",
            });
            expect(scope.isDone()).toBe(true);
            expect(mockPrintJson).toHaveBeenCalledWith({
                deleted: true,
                hostname: "api.example.com",
                deploymentName: "deployment-a",
            });
        });
        it("should auto-resolve a single deployment assignment before deleting", async () => {
            const listScope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .get(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                data: [
                    {
                        id: "cd_1",
                        accountName: TEST_ACCOUNT_NAME,
                        projectName: "project-a",
                        hostname: "api.example.com",
                        provider: "cloudflare",
                        deployments: [
                            {
                                deploymentName: "deployment-a",
                                branch: "main",
                                environmentType: "PRODUCTION",
                                isDefault: true,
                                stage: "api",
                                cname: "cname.zuplo.api",
                            },
                        ],
                    },
                ],
                offset: 0,
                limit: 100,
            });
            const deleteScope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .delete(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains?hostname=api.example.com&deploymentName=deployment-a`)
                .reply(204);
            listScope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            deleteScope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await executeCustomDomainCommand("delete", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
            });
            expect(listScope.isDone()).toBe(true);
            expect(deleteScope.isDone()).toBe(true);
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-delete-autoresolve-requests");
        });
        it("should fail locally when the hostname is assigned to multiple deployments", async () => {
            const listScope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .get(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                data: [
                    {
                        id: "cd_1",
                        accountName: TEST_ACCOUNT_NAME,
                        projectName: "project-a",
                        hostname: "api.example.com",
                        provider: "cloudflare",
                        deployments: [
                            {
                                deploymentName: "deployment-a",
                                branch: "main",
                                environmentType: "PRODUCTION",
                                isDefault: true,
                                stage: "api",
                                cname: "cname.zuplo.api",
                            },
                            {
                                deploymentName: "deployment-b",
                                branch: "preview",
                                environmentType: "PREVIEW",
                                isDefault: false,
                                stage: "api",
                                cname: "cname.zuplo.api",
                            },
                        ],
                    },
                ],
                offset: 0,
                limit: 100,
            });
            listScope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await expect(executeCustomDomainCommand("delete", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "api.example.com",
            })).rejects.toThrow("Process would exit");
            expect(listScope.isDone()).toBe(true);
            expect(mockPrintCriticalFailure).toHaveBeenCalledWith("Error: Custom domain api.example.com is assigned to multiple deployments. Rerun with --deployment-name.");
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-delete-multi-assignment-requests");
        });
        it("should handle delete API errors", async () => {
            const listScope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .get(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains`)
                .reply(200, {
                data: [],
                offset: 0,
                limit: 100,
            });
            const scope = setupAuthenticatedNock(nock(TEST_API_BASE))
                .delete(`/v1/accounts/${TEST_ACCOUNT_NAME}/custom-domains?hostname=missing.example.com`)
                .reply(404, {
                title: "Not Found",
                detail: "The custom domain was not found on this account",
                status: 404,
            });
            listScope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            scope.on("request", (req, interceptor, body) => {
                requestCapture.capture(req, interceptor, body);
            });
            await expect(executeCustomDomainCommand("delete", {
                account: TEST_ACCOUNT_NAME,
                "api-key": TEST_AUTH_TOKEN,
                hostname: "missing.example.com",
                "deployment-name": undefined,
            })).rejects.toThrow("Failed to delete custom domain for account");
            expect(listScope.isDone()).toBe(true);
            expect(scope.isDone()).toBe(true);
            expect(mockPrintDiagnostics).toHaveBeenCalledWith("Error: Failed to delete custom domain for your account. Check the arguments.", {
                title: "Not Found",
                detail: "The custom domain was not found on this account",
                status: 404,
            });
            expect(requestCapture.getRequests()).toMatchSnapshot("custom-domain-delete-error-requests");
        });
    });
});
//# sourceMappingURL=custom-domain.integration.test.js.map