import { Resource, ResourceKind } from "../resource.js";
import { handleApiError } from "./api-error.js";
import { createCloudflareApi } from "./api.js";
import { resolveEmailZoneId } from "./email-common.js";
export function isEmailRule(resource) {
    return resource?.[ResourceKind] === "cloudflare::EmailRule";
}
function validateMatchers(matchers) {
    for (const matcher of matchers) {
        if (matcher.type === "all") {
            continue;
        }
        if (matcher.field !== "to") {
            throw new Error('EmailRule literal matchers currently only support field: "to".');
        }
        if (!matcher.value) {
            throw new Error("EmailRule literal matchers require a value.");
        }
    }
}
function validateActions(actions) {
    for (const action of actions) {
        if (action.type === "drop") {
            continue;
        }
        if (!action.value?.length) {
            throw new Error(`EmailRule action "${action.type}" requires at least one value.`);
        }
    }
}
/**
 * Creates email routing rules that define how emails sent to your domain are processed.
 * Rules are evaluated in priority order (lower number = higher priority).
 *
 * @example
 * ## Forward emails to a specific address
 *
 * Forward all emails sent to info@example.com to a destination address.
 *
 * ```ts
 * const infoRule = await EmailRule("info-forwarding", {
 *   zone: "example.com",
 *   name: "Forward info emails",
 *   matchers: [
 *     {
 *       type: "literal",
 *       field: "to",
 *       value: "info@example.com"
 *     }
 *   ],
 *   actions: [
 *     {
 *       type: "forward",
 *       value: ["admin@company.com"]
 *     }
 *   ]
 * });
 * ```
 *
 * @example
 * ## Process emails with a Worker
 *
 * Route emails to a Cloudflare Worker for custom processing.
 *
 * ```ts
 * const workerRule = await EmailRule("worker-processing", {
 *   zone: "example.com",
 *   name: "Process with Worker",
 *   priority: 1,
 *   matchers: [
 *     {
 *       type: "literal",
 *       field: "to",
 *       value: "webhook@example.com"
 *     }
 *   ],
 *   actions: [
 *     {
 *       type: "worker",
 *       value: ["email-processor"]
 *     }
 *   ]
 * });
 * ```
 *
 * @example
 * ## Multiple matchers and actions
 *
 * Create a rule with multiple conditions and actions.
 *
 * ```ts
 * const complexRule = await EmailRule("support-routing", {
 *   zone: "example.com",
 *   name: "Support email routing",
 *   priority: 2,
 *   matchers: [
 *     {
 *       type: "literal",
 *       field: "to",
 *       value: "support@example.com"
 *     }
 *   ],
 *   actions: [
 *     {
 *       type: "forward",
 *       value: ["support@company.com", "backup@company.com"]
 *     }
 *   ]
 * });
 * ```
 */
export const EmailRule = Resource("cloudflare::EmailRule", async function (_id, props) {
    const api = await createCloudflareApi(props);
    const zoneId = await resolveEmailZoneId(api, props.zone);
    validateMatchers(props.matchers);
    validateActions(props.actions);
    if (this.phase === "delete") {
        if (this.output?.ruleId) {
            const response = await api.delete(`/zones/${zoneId}/email/routing/rules/${this.output.ruleId}`);
            if (!response.ok && response.status !== 404) {
                await handleApiError(response, "delete", "email rule");
            }
        }
        return this.destroy();
    }
    if (this.phase === "update" && this.output) {
        // Update the existing rule
        const updatePayload = {
            name: props.name || this.output.name,
            enabled: props.enabled ?? true,
            priority: props.priority ?? 0,
            matchers: props.matchers,
            actions: props.actions,
        };
        const response = await api.put(`/zones/${zoneId}/email/routing/rules/${this.output.ruleId}`, updatePayload);
        if (!response.ok) {
            if (response.status === 404) {
                // Rule was deleted externally, create a new one
            }
            else {
                await handleApiError(response, "update", "email rule");
            }
        }
        else {
            const result = (await response.json());
            return {
                zoneId,
                ruleId: result.result.id,
                name: result.result.name,
                enabled: result.result.enabled,
                priority: result.result.priority,
                matchers: result.result.matchers,
                actions: result.result.actions,
                tag: result.result.tag || undefined,
            };
        }
    }
    // Create new rule
    const createPayload = {
        name: props.name || "Email routing rule",
        enabled: props.enabled ?? true,
        priority: props.priority ?? 0,
        matchers: props.matchers,
        actions: props.actions,
    };
    const createResponse = await api.post(`/zones/${zoneId}/email/routing/rules`, createPayload);
    if (!createResponse.ok) {
        await handleApiError(createResponse, "create", "email rule");
    }
    const result = (await createResponse.json());
    return {
        zoneId,
        ruleId: result.result.id,
        name: result.result.name,
        enabled: result.result.enabled,
        priority: result.result.priority,
        matchers: result.result.matchers,
        actions: result.result.actions,
        tag: result.result.tag || undefined,
    };
});
//# sourceMappingURL=email-rule.js.map