import * as hono from 'hono';
import { OpenAPIHono } from '@hono/zod-openapi';
import { PermissionTree } from '@mesob/common';
import { D as Database } from './index-D90p-4Uh.js';

type Tenant = {
    id: string;
    name: unknown;
    description: unknown;
    isActive: boolean;
};

type SessionStatus = 'valid' | 'no_cookie' | 'invalid_session' | 'user_not_found' | 'error';

type AuthEnv = {
    Variables: {
        config: AuthConfig;
        database: Database;
        tenantId: string;
        tenant?: Tenant | null;
        host?: string | null;
        userId?: string;
        user?: User;
        session?: Session;
        sessionStatus?: SessionStatus;
    };
};

declare const createAuthRoutes: ({ config, database, }: CreateAuthRoutesOptions) => OpenAPIHono<AuthEnv, {}, "/">;

type User = {
    id: string;
    tenantId: string;
    fullName: string;
    email: string | null;
    phone: string | null;
    handle: string;
    image: string | null;
    emailVerified: boolean;
    phoneVerified: boolean;
    lastSignInAt: string | null;
    bannedUntil?: string | null;
    loginAttempt?: number;
    /** Role IDs */
    roles?: string[] | null;
    /** Role codes for hasRole() checks (e.g. 'owner', 'tenant-admin') */
    roleCodes?: string[] | null;
    /** Permission IDs for hasPermission() checks */
    permissions?: string[] | null;
};
type SessionMeta = {
    action?: string;
    rememberMe?: boolean;
};
type Session = {
    id: string;
    tenantId: string;
    userId: string;
    expiresAt: string;
    createdAt: string;
    meta?: SessionMeta | null;
};
type SendVerificationOTPParams = {
    email?: string;
    phone?: string;
    code: string;
    hash: string;
    type: string;
};
type SendInvitationParams = {
    email?: string;
    phone?: string;
    fullName: string;
    identifier: string;
    inviteUrl?: string;
    tenantId: string;
};
type VerificationConfig = {
    enabled: boolean;
    required: boolean;
    otpLength: number;
    expiresIn: string;
    maxAttempts: number;
    resendInterval?: string;
    sendVerificationOTP?: (params: SendVerificationOTPParams) => Promise<void> | void;
    sendInvitation?: (params: SendInvitationParams) => Promise<void> | void;
};
type PhoneConfig = VerificationConfig & {
    phoneRegex?: RegExp | string;
};
type EmailConfig = VerificationConfig;
type SignUpConfig = {
    enabled: boolean;
    emailEnabled: boolean;
    phoneEnabled: boolean;
    allowedEmailDomains?: readonly string[];
};
type EmailNormalizationConfig = {
    gmailAlias?: boolean;
};
type TurnstileActionConfig = {
    signUp?: string;
    signIn?: string;
    forgotPassword?: string;
};
type TurnstileConfig = {
    enabled: false;
} | {
    enabled: true;
    secretKey: string;
    siteKey?: string;
    actions?: TurnstileActionConfig;
};
/** Telegram Login (OIDC) — https://core.telegram.org/bots/telegram-login */
type TelegramConfig = {
    enabled: boolean;
    /** Bot Client ID from @BotFather Web Login */
    clientId: string;
    clientSecret?: string;
    /** Allow new user when phone not found. Default: `signUp.enabled` */
    allowSignUp?: boolean;
    lang?: string;
};
type SessionConfig = {
    /** Default session duration (e.g., '365d', '30d'). Default: '365d' */
    expiresIn: string;
    /** Session duration when "remember me" is checked (e.g., '30d'). Default: '30d' */
    rememberMeExpiresIn: string;
    /** Session duration when "remember me" is unchecked (e.g., '1h'). Default: '1h' */
    shortSessionExpiresIn: string;
    /** Refresh session if remaining time is less than this (e.g., '1d'). Default: '1d' */
    updateAge: string;
    /** Refresh short session if remaining time is less than this (e.g., '15m'). Default: '15m' */
    shortSessionUpdateAge: string;
    /** Maximum concurrent sessions per user */
    maxPerUser?: number;
};
type SecurityConfig = {
    maxLoginAttempts: number;
    lockoutDuration: string;
};
type TenantConfig = {
    enabled?: boolean;
    tenantId?: string;
    tenantDomains?: string[];
};
type DocsConfig = {
    enabled?: boolean;
    title?: string;
    version?: string;
    theme?: 'default' | 'moon' | 'purple' | 'saturn' | 'bluePlanet' | 'kepler' | 'mars';
    servers?: Array<{
        url: string;
        description?: string;
    }>;
};
type SeedRole = {
    code: string;
    name: unknown;
    description?: unknown;
    permissionIds?: readonly string[];
    isSystem?: boolean;
    isEditable?: boolean;
    isDeletable?: boolean;
};
type SeedScope = {
    code: string;
    name: string;
    description?: string;
    meta?: unknown;
};
/** KV subset for session cache + rate limits (e.g. Cloudflare KVNamespace). */
type AuthKvStorage = {
    get(key: string): Promise<string | null | undefined>;
    put(key: string, value: string, options?: {
        expirationTtl?: number;
    }): Promise<void>;
    delete(key: string): Promise<void>;
};
type SessionCacheConfig = {
    enabled: false;
} | {
    enabled: true;
    kv: AuthKvStorage;
    /** Cache entry TTL in seconds */
    ttlSeconds?: number;
};
type AuthRateLimitConfig = {
    enabled: false;
} | {
    enabled: true;
    kv: AuthKvStorage;
    /** Window length in seconds */
    window: number;
    /** Max requests per window per IP (and per route bucket in impl) */
    max: number;
    /** Shown on 429 for auth-react */
    message?: string;
    /** Default cf-connecting-ip; impl may fall back to x-forwarded-for */
    ipHeader?: string;
    /**
     * IPv6 rate-limit bucket: mask to this prefix length (1–128).
     * 128 = full address; 64 = typical LAN; 48 / 32 = larger nets. Default 64.
     * IPv4 always uses the full address. IPv4-mapped IPv6 → IPv4 key.
     */
    ipv6Subnet?: number;
};
type AuthConfig = {
    connectionString: string;
    userType: string;
    secret: string;
    basePath?: string;
    /**
     * Session cookie name + KV session cache key namespace (`{prefix}_session_token`, `{prefix}:sc:v1:…`).
     * Default `msb`. Align with auth-react `prefix`.
     */
    prefix?: string;
    tenant?: TenantConfig;
    docs?: DocsConfig;
    permissions?: PermissionTree;
    roles?: SeedRole[];
    scopes?: SeedScope[];
    session: SessionConfig;
    email: EmailConfig;
    phone: PhoneConfig;
    signUp?: SignUpConfig;
    emailNormalization?: EmailNormalizationConfig;
    turnstile?: TurnstileConfig;
    telegram?: TelegramConfig;
    security?: SecurityConfig;
    /** Session+user cache in KV; DB remains source of truth when disabled */
    sessionCache?: SessionCacheConfig;
    /** Abuse guard on unauthenticated auth routes; separate KV from sessionCache */
    rateLimit?: AuthRateLimitConfig;
};

type CreateAuthRoutesOptions = {
    config: AuthConfig;
    database: Database;
};
type MesobAuth = {
    routes: ReturnType<typeof createAuthRoutes>;
    getSession: (c: hono.Context) => Promise<{
        session: Session | null;
        user: User | null;
        sessionToken: string | null;
    }>;
    tenantMiddleware: hono.MiddlewareHandler;
    sessionMiddleware: hono.MiddlewareHandler;
};

export type { AuthConfig as A, MesobAuth as M, Session as S, TelegramConfig as T, User as U, SessionConfig as a, SeedRole as b, SeedScope as c, AuthEnv as d, AuthKvStorage as e, AuthRateLimitConfig as f, SendInvitationParams as g, SendVerificationOTPParams as h, SessionCacheConfig as i, SessionStatus as j, Tenant as k };
