import { z } from "zod";
import { brandedString } from "./branded-string.js";
const SLUG_REGEX = /^[a-z0-9][a-z0-9-]*$/;
const TEAM_ID_REGEX = /^ailf\.team\.[a-z0-9][a-z0-9-]*$/;
const TeamMemberSchema = z
    .object({
    email: z.string().email().optional(),
    sanityUserId: z.string().optional(),
    githubUsername: z.string().optional(),
    displayName: z.string().optional(),
    role: z.string().optional(),
    lastVerifiedAt: z.string().datetime().optional(),
})
    .refine((m) => Boolean(m.email || m.sanityUserId || m.githubUsername), {
    message: "TeamMember requires at least one of email, sanityUserId, githubUsername",
});
const ChannelScopeSchema = z.discriminatedUnion("type", [
    z.object({ type: z.literal("owned") }),
    z.object({ type: z.literal("all") }),
    z.object({ type: z.literal("areas"), areas: z.array(z.string()) }),
    z.object({ type: z.literal("repos"), repos: z.array(z.string()) }),
    z.object({ type: z.literal("tags"), tags: z.array(z.string()) }),
]);
const DeliverySchema = z.enum(["immediate", "daily", "weekly"]).optional();
const SlackChannelSchema = z.object({
    _key: z.string(),
    type: z.literal("slack"),
    channelId: z.string().min(1),
    channelName: z.string().optional(),
    purpose: z.string().optional(),
    events: z.array(z.string()).optional(),
    scope: ChannelScopeSchema.optional(),
    delivery: DeliverySchema,
});
const EmailChannelSchema = z.object({
    _key: z.string(),
    type: z.literal("email"),
    addresses: z.array(z.string().email()).min(1),
    purpose: z.string().optional(),
    events: z.array(z.string()).optional(),
    scope: ChannelScopeSchema.optional(),
    delivery: DeliverySchema,
});
const WebhookChannelSchema = z.object({
    _key: z.string(),
    type: z.literal("webhook"),
    logicalName: z.string().min(1),
    purpose: z.string().optional(),
    events: z.array(z.string()).optional(),
    scope: ChannelScopeSchema.optional(),
    delivery: DeliverySchema,
});
const NotificationChannelSchema = z.discriminatedUnion("type", [
    SlackChannelSchema,
    EmailChannelSchema,
    WebhookChannelSchema,
]);
export const TeamSchema = z.object({
    id: brandedString(TEAM_ID_REGEX),
    slug: brandedString(SLUG_REGEX),
    displayName: z.string().min(1),
    description: z.string().optional(),
    status: z.enum(["active", "archived"]),
    members: z.array(TeamMemberSchema).min(1),
    repos: z.array(z.string()).optional(),
    notifications: z.array(NotificationChannelSchema).optional(),
});
/**
 * A team loaded for **notification delivery**, where the roster is irrelevant.
 *
 * `matchReportToChannels` routes by `report.provenance.owner.team` plus each
 * channel's `scope` / `events`; it never reads `members`. Membership is modeled
 * user-side as `ailf.user.teams[]` (self-declared affiliation — personalization
 * only, D0075) and never populates the team-side `members[]` roster, which is
 * Studio-authored and empty for nearly every team. So `TeamSchema`'s
 * `members.min(1)` — correct for the team-as-ownership-entity contract — would
 * wrongly drop every channel-bearing but member-less team from the subscription
 * read. This view relaxes only that one constraint; `slug`, `status`, and the
 * `notifications[]` discriminated union are still validated, so a malformed
 * channel is still skipped. `TeamSchema` itself is unchanged.
 */
export const SubscribedTeamSchema = TeamSchema.extend({
    members: z.array(TeamMemberSchema),
});
