import type { MembershipSummary } from "@riverbankcms/billing/membership";
import type { BillingInterval } from "@riverbankcms/billing/plans/types";
import type { CamelizeKeys, DbRow, SupportedAdminRole } from "@riverbankcms/db";
import type { PageRecord } from "./contentRuntime";
import type { SiteDeploymentMode } from "./siteSettings";
import type { SiteRole } from "./siteMembers";
/**
 * Access, Domain, and Admin Contracts
 *
 * These types group the account-access surface that still lives at the API layer:
 * site membership/invitations, account/auth flows, domain management, MFA, and
 * admin invite/user/billing override operations.
 *
 * Note: Do NOT use these API types as validation schemas. They capture wire shapes,
 * while the owning auth/domain/admin services still validate and normalize inputs.
 */
type AdminInviteRow = DbRow<"admin_invites">;
type AllowedEmailDomainRow = DbRow<"allowed_email_domains">;
export type AdminInvite = CamelizeKeys<AdminInviteRow>;
export type AllowedEmailDomain = CamelizeKeys<AllowedEmailDomainRow>;
export type SiteMemberProfile = {
    displayName: string | null;
    avatarUrl: string | null;
};
export type SiteMember = {
    id: string;
    siteId: string;
    userId: string;
    role: SiteRole;
    invitedBy: string | null;
    acceptedAt: string | null;
    removedAt: string | null;
    createdAt: string;
    updatedAt: string;
    profile: SiteMemberProfile | null;
    email: string | null;
    isCurrentUser: boolean;
};
export type DeleteAccountRequest = {
    confirmation: string;
};
export type DeleteAccountResponse = {
    success: boolean;
};
export type SiteInvitation = {
    id: string;
    siteId: string;
    email: string;
    role: SiteRole;
    invitedBy: string | null;
    expiresAt: string | null;
    acceptedAt: string | null;
    acceptedBy: string | null;
    revokedAt: string | null;
    metadata?: Record<string, unknown> | null;
    createdAt: string;
    updatedAt: string;
};
export type SiteAccessSummary = {
    membershipRole: SiteRole | null;
    canInvite: boolean;
    canManage: boolean;
    canTransferOwnership: boolean;
};
export type SitePlanSummaryResponse = {
    planId: string;
    maxCollaborators: number | null;
    canInviteEditors: boolean;
    canInviteAdmins: boolean;
    currentCollaborators: number;
};
export type ListSiteMembersResponse = {
    members: SiteMember[];
    invitations: SiteInvitation[];
    access: SiteAccessSummary;
    plan: SitePlanSummaryResponse;
};
export type AuthFieldKey = "email" | "password" | "confirmPassword" | "name" | "terms" | "magicLink";
export type AuthSubmissionErrorReason = "validation" | "spam_protection" | "supabase" | "already_registered" | "rate_limited" | "email" | "closed" | "invalid_credentials" | "not_confirmed" | "not_allowed";
export type AuthSubmissionSuccess = {
    status: "success";
    message: string;
    redirectTo?: string;
    flash?: Record<string, unknown>;
};
export type AuthSubmissionError = {
    status: "error";
    reason: AuthSubmissionErrorReason;
    message: string;
    fieldErrors?: Partial<Record<AuthFieldKey, string>>;
    retryAfterSeconds?: number;
};
export type AuthSubmissionResult = AuthSubmissionSuccess | AuthSubmissionError;
export type ReauthSubmissionResult = AuthSubmissionResult & {
    setReenrollCookie?: boolean;
};
export type DomainAvailability = {
    domain: string;
    available: boolean;
    price?: number;
    currency?: string;
    premium?: boolean;
    reason?: string;
    source?: "lookup" | "suggestion" | "heuristic";
};
export type SiteDomainRecord = CamelizeKeys<DbRow<"site_domains">>;
export type SiteDomainContactPayload = {
    firstName: string;
    lastName: string;
    organization?: string;
    addressLine1: string;
    addressLine2?: string;
    city: string;
    state: string;
    postalCode: string;
    country: string;
    phone: string;
    email: string;
};
export type LookupSiteDomainRequest = {
    query: string;
};
export type LookupSiteDomainResponse = {
    domains: DomainAvailability[];
};
export type RegisterSiteDomainRequest = {
    domain: string;
    useProfileContact?: boolean;
    contact?: SiteDomainContactPayload;
    saveContactToProfile?: boolean;
};
export type RegisterSiteDomainResponse = {
    domain: SiteDomainRecord;
};
export type AddCustomDomainRequest = {
    domain: string;
};
export type AddCustomDomainResponse = {
    domain: SiteDomainRecord;
    vercel: {
        verified: boolean;
        verification?: Array<{
            type: string;
            domain: string;
            value: string;
            reason: string;
        }>;
    };
};
export type DomainSearchResultResponse = {
    query: string;
    primary: DomainAvailability | null;
    tldAlternatives: DomainAvailability[];
    nameVariants: DomainAvailability[];
    suggestions: DomainAvailability[];
    errors: string[];
};
export type RegisterDomainContactInput = SiteDomainContactPayload;
export type RegisterDomainRequestPayload = {
    siteId: string;
    domain: string;
    years?: number;
    quotedPrice?: number;
    quotedCurrency?: string;
    quotedPremium?: boolean;
    useProfileContact?: boolean;
    contact?: RegisterDomainContactInput;
    saveContactToProfile?: boolean;
};
export type DomainConfigResult = {
    status: "pending_vercel" | "pending_email" | "pending_dns" | "ready" | "failed";
    error?: string;
    vercelVerified?: boolean;
    resendDomainId?: string;
};
export type RegisterDomainResponse = {
    domain: SiteDomainRecord;
    registration: {
        orderId: string;
        status: string;
    };
    configResult: DomainConfigResult;
};
export type RegistrarLifecycleState = "registered" | "configuring" | "awaiting_registrant_verification" | "ready" | "renewal_at_risk" | "renewal_failed" | "transfer_out_requested" | "expired" | "redemption" | "suspended";
export type RegistrarLifecycleMutationOutcome = "succeeded" | "pending" | "repaired";
export type RegistrarLifecycleMutationOperation = "update_contact" | "enable_privacy" | "disable_privacy" | "enable_auto_renew" | "disable_auto_renew" | "unlock" | "retrieve_epp";
export type RegistrarLifecycleMutationBase<TOperation extends RegistrarLifecycleMutationOperation> = {
    operation: TOperation;
    outcome: RegistrarLifecycleMutationOutcome;
    lifecycleState?: RegistrarLifecycleState;
    responseCode?: number;
    providerDetail?: string;
};
export type RegistrarLifecycleMutationResponse = RegistrarLifecycleMutationBase<"update_contact"> | (RegistrarLifecycleMutationBase<"enable_privacy" | "disable_privacy"> & {
    privacyEnabled: boolean;
}) | (RegistrarLifecycleMutationBase<"enable_auto_renew" | "disable_auto_renew"> & {
    autoRenew: boolean;
}) | (RegistrarLifecycleMutationBase<"unlock"> & {
    lifecycleState: "transfer_out_requested";
}) | (RegistrarLifecycleMutationBase<"retrieve_epp"> & {
    lifecycleState: "transfer_out_requested";
} & ({
    eppCodeDelivery: "provider_delivered";
} | {
    eppCodeDelivery: "returned";
    eppCode: string;
}));
export type ExposedRegistrarLifecycleMutationResponse = Extract<RegistrarLifecycleMutationResponse, {
    operation: "update_contact" | "enable_privacy" | "disable_privacy" | "enable_auto_renew" | "disable_auto_renew";
}>;
export type RegistrarLifecycleResponse = {
    domain: SiteDomainRecord;
    mutation: ExposedRegistrarLifecycleMutationResponse;
};
export type RegistrarBooleanMutationRequest = {
    enabled: boolean;
};
export type RegistrarRenewalCostEstimate = {
    amount: number;
    currency?: string;
    source: "provider_quote" | "manual" | "last_registration";
};
export type RegistrarProviderName = "namesilo";
export type RegistrarRenewalRiskReason = "auto_renew_disabled" | "insufficient_registrar_funds";
export type RegistrarRenewalManualReviewReason = "not_managed_by_registrar" | "registered_domain_missing_registrar" | "missing_expiry" | "invalid_expiry" | "invalid_registrar_balance" | "invalid_renewal_cost_estimate" | "missing_renewal_cost_estimate" | "registrar_balance_unavailable" | "registrar_balance_unsupported" | "currency_mismatch";
export type RegistrarRenewalManualReviewReasonWithoutExpiry = "not_managed_by_registrar" | "registered_domain_missing_registrar" | "missing_expiry" | "invalid_expiry";
export type RegistrarRenewalManualReviewReasonWithExpiry = Exclude<RegistrarRenewalManualReviewReason, RegistrarRenewalManualReviewReasonWithoutExpiry>;
export type RegistrarRenewalFailedReason = "past_expiry" | "renewal_failed_lifecycle" | "expired_lifecycle" | "redemption_lifecycle" | "suspended_lifecycle";
export type RegistrarRenewalPosture = {
    kind: "funded";
    domain: string;
    provider: RegistrarProviderName;
    expiresAt: string;
    daysUntilExpiry: number;
    availableBalance: number;
    renewalCost: RegistrarRenewalCostEstimate;
} | {
    kind: "at_risk";
    domain: string;
    provider: RegistrarProviderName;
    expiresAt: string;
    daysUntilExpiry: number;
    reasons: readonly [RegistrarRenewalRiskReason, ...RegistrarRenewalRiskReason[]];
    availableBalance?: number;
    renewalCost?: RegistrarRenewalCostEstimate;
} | {
    kind: "failed";
    domain: string;
    provider: RegistrarProviderName | null;
    reason: RegistrarRenewalFailedReason;
    expiresAt: string;
} | {
    kind: "manual_review";
    domain: string;
    provider: RegistrarProviderName | null;
    reason: RegistrarRenewalManualReviewReasonWithoutExpiry;
} | {
    kind: "manual_review";
    domain: string;
    provider: RegistrarProviderName;
    reason: RegistrarRenewalManualReviewReasonWithExpiry;
    expiresAt: string;
};
export type RegistrarAccountBalance = {
    success: true;
    provider: RegistrarProviderName;
    availableBalance: number;
    currency?: string;
    rawBalance: string;
} | {
    success: false;
    provider: RegistrarProviderName;
    reason: "unsupported" | "provider_error";
    error: string;
};
export type RegistrarRenewalPostureResponse = {
    domain: SiteDomainRecord;
    posture: RegistrarRenewalPosture;
    checkedAt: string;
    renewalCost?: RegistrarRenewalCostEstimate;
    accountBalance?: RegistrarAccountBalance;
};
export type SetHomepageRequest = {
    pageId: string;
};
export type SetHomepageResponse = {
    homepage: PageRecord;
    previous?: PageRecord | null;
};
export type BulkOperationResult = {
    succeeded: number;
    failed: number;
    errors?: Array<{
        entryId: string;
        error: string;
    }>;
};
export type InviteSiteMemberRequest = {
    email: string;
    role: "team_member";
    staffMemberId: string;
} | {
    email: string;
    role: "editor" | "administrator" | "event_host";
};
export type InviteSiteMemberEmailResult = {
    ok: true;
} | {
    ok: false;
    error: string;
};
export type InviteSiteMemberResponse = {
    invitation: SiteInvitation;
    token: string;
    email?: InviteSiteMemberEmailResult;
};
export type UpdateSiteMemberRoleRequest = {
    role: Exclude<SiteRole, "owner" | "team_member">;
};
export type UpdateSiteMemberRoleResponse = {
    member: SiteMember;
};
export type RemoveSiteMemberResponse = {
    success: boolean;
};
export type RevokeSiteInvitationResponse = {
    invitation: SiteInvitation | null;
};
export type TransferSiteOwnershipRequest = {
    memberId: string;
};
export type TransferSiteOwnershipResponse = {
    siteId: string;
    ownerId: string;
};
export type AuthInviteContinueRequest = {
    token: string;
};
export type AuthInviteContinueResponse = {
    redirectTo: string;
};
export type AuthInviteRegisterRequest = {
    token: string;
    name: string;
    password?: string;
    confirmPassword?: string;
    acceptTerms: boolean;
};
export type AuthInviteRegisterResponse = {
    redirectTo: string;
};
export type AuthResetCompleteRequest = {
    newPassword: string;
};
export type AuthResetCompleteResponse = {
    ok: boolean;
    passwordSetAt: string;
};
export type AcceptSiteInvitationRequest = {
    token: string;
};
export type AcceptSiteInvitationResponse = {
    membership: SiteMember;
};
export type MfaFactorSummary = {
    id: string;
    type: "totp" | "phone" | (string & {});
    status: "verified" | "unverified" | "pending" | "failed" | (string & {});
    friendlyName: string | null;
    createdAt: string | null;
    updatedAt: string | null;
};
export type MfaOverviewPayload = {
    userId: string;
    requiresEnrollment: boolean;
    mfaEnrolled: boolean;
    mfaEnrolledAt: string | null;
    factors: MfaFactorSummary[];
    verifiedCount: number;
    totpFactors: MfaFactorSummary[];
    pendingTotpFactor: MfaFactorSummary | null;
    loadError: string | null;
};
export type MfaTotpEnrollResponse = {
    factorId: string;
    type: "totp";
    friendlyName: string | null;
    secret: string;
    uri: string;
    qrCode: string;
    challengeId: string;
    challengeExpiresAt: number;
};
export type MfaTotpVerifyRequest = {
    factorId: string;
    code: string;
    challengeId?: string | null;
};
export type MfaTotpVerifyResponse = {
    factorId: string;
    challengeId: string;
    expiresIn: number;
    mfaVerified: true;
};
export type MfaTotpActivateRequest = {
    requireEnrollment?: boolean;
};
export type MfaOverviewResponse = {
    overview: MfaOverviewPayload;
};
export type MfaPhoneEnrollRequest = {
    phone: string;
    friendlyName?: string;
};
export type MfaPhoneEnrollResponse = {
    factorId: string;
    phone: string;
    friendlyName: string | null;
    challengeId: string;
    challengeExpiresAt: string | number;
};
export type MfaPhoneChallengeRequest = {
    factorId: string;
};
export type MfaPhoneChallengeResponse = {
    factorId: string;
    challengeId: string;
    challengeExpiresAt: string | number;
};
export type MfaPhoneVerifyRequest = {
    factorId: string;
    code: string;
    challengeId?: string | null;
    requireEnrollment?: boolean;
};
export type MfaBackupCodeSummary = {
    sequence: number;
    codeHint: string;
    usedAt: string | null;
};
export type MfaBackupCodesOverview = {
    batchId: string | null;
    rotatedAt: string | null;
    totalCodes: number;
    unusedCodes: number;
    codes: MfaBackupCodeSummary[];
};
export type MfaBackupCodesOverviewResponse = {
    overview: MfaBackupCodesOverview;
};
export type MfaBackupCodesRotateResponse = {
    batchId: string;
    rotatedAt: string;
    count: number;
    codes: string[];
};
export type CreateAdminInviteRequest = {
    email: string;
    role: SupportedAdminRole;
    tenantId?: string | null;
    expiresAt?: string | null;
    metadata?: Record<string, unknown> | null;
};
export type CreateAdminInviteResponse = {
    invite: AdminInvite;
    token: string;
};
export type ListAdminInvitesResponse = {
    invites: AdminInvite[];
};
export type RevokeAdminInviteResponse = {
    invite: AdminInvite;
};
export type CreateAdminUserRequest = {
    email: string;
    displayName?: string;
    sendInvite?: boolean;
};
export type CreateAdminUserResponse = {
    user: {
        id: string;
        email: string;
        displayName?: string;
        createdAt: string;
    };
    inviteSent: boolean;
};
export type AcceptAdminInviteRequest = {
    token: string;
};
export type AcceptAdminInviteResponse = {
    invite: AdminInvite;
};
export type ListAllowedDomainsResponse = {
    domains: AllowedEmailDomain[];
};
export type CreateAllowedDomainRequest = {
    domain: string;
    tenantId?: string | null;
};
export type CreateAllowedDomainResponse = {
    domain: AllowedEmailDomain;
};
export type DeleteAllowedDomainResponse = {
    domain: AllowedEmailDomain;
};
export type AdminCreateSiteRequest = {
    title: string;
    slug: string;
    ownerEmail: string;
    deploymentMode: SiteDeploymentMode;
};
export type AdminCreateSiteResponse = {
    site: {
        id: string;
        title: string;
        slug: string;
        deployment_mode: SiteDeploymentMode;
        created_at: string;
    };
};
export type AdminOwnedSiteSummary = {
    id: string;
    title: string;
    slug: string;
};
export type AdminDeleteSiteResponse = {
    ok: true;
    deletedSiteId: string;
};
export type AdminDeleteUserResponse = {
    ok: true;
    deletedUserId: string;
    deletedSiteIds: string[];
} | {
    ok: false;
    reason: "owns_sites";
    ownedSites: AdminOwnedSiteSummary[];
} | {
    ok: false;
    reason: "self_delete_forbidden";
} | {
    ok: false;
    reason: "fk_restrict";
    message: string;
} | {
    ok: false;
    reason: "auth_delete_failed";
    message: string;
} | {
    ok: false;
    reason: "site_delete_failed";
    deletedSiteIds: string[];
    failedSiteId: string;
    message: string;
};
export type ChangePlanRequest = {
    planId: string;
    interval: BillingInterval;
    prorationBehavior?: "create_prorations" | "always_invoice" | "none";
};
export type ChangePlanResponse = {
    membership: MembershipSummary | null;
};
export type AdminChangePlanRequest = ChangePlanRequest & {
    userId: string;
    reason?: string;
    bypassProration?: boolean;
};
export type AdminChangePlanResponse = ChangePlanResponse;
export type BillingPriceOverride = {
    id: string;
    userId: string;
    planId: string;
    interval: "month" | "year";
    amountCents: number;
    currency: string;
    validFrom: string | null;
    validUntil: string | null;
    isActive: boolean;
    createdBy: string | null;
    reason: string | null;
    createdAt: string;
    updatedAt: string;
};
export type AdminGetPriceOverrideQuery = {
    userId: string;
    planId: string;
    interval: "month" | "year";
};
export type AdminGetPriceOverrideResponse = {
    hasOverride: boolean;
    override: BillingPriceOverride | null;
    formattedPrice: string | null;
};
export type AdminUpsertPriceOverrideRequest = {
    userId: string;
    planId: string;
    interval: "month" | "year";
    amountCents: number;
    currency?: string;
    validFrom?: string | null;
    validUntil?: string | null;
    reason?: string;
};
export type AdminUpsertPriceOverrideResponse = {
    override: BillingPriceOverride;
};
export type AdminDeletePriceOverrideRequest = {
    userId: string;
    planId: string;
    interval: "month" | "year";
    reason?: string;
};
export type AdminDeletePriceOverrideResponse = {
    success: true;
};
export {};
