declare module '@taukala/xs-ctrl' {
  /**
   * Session object type (generic to allow custom session types)
   */
  export type Session = any;

  /**
   * Claims object structure representing user permissions and attributes
   * @example
   * {
   *   role: ['admin', 'user'],
   *   department: ['IT'],
   *   businessOwner: ['business-1', 'business-2']
   * }
   */
  export interface Claims {
    [key: string]: (string | number)[];
  }

  /**
   * Context object for validation containing session, claims, and custom resources
   */
  export interface ValidationContext {
    session?: Session;
    claims?: Claims;
    resources?: Record<string, any>;
    [key: string]: any;
  }

  /**
   * Static condition type representing [key, allowedValues] pairs
   */
  export type Condition = [string, (string | number)[]];

  /**
   * Dynamic validator function type for complex authorization rules
   */
  export type DynamicValidator = (context: ValidationContext) => boolean | Promise<boolean>;

  /**
   * Access rule structure containing static conditions and dynamic validators
   */
  export interface AccessRule {
    conditions: Condition[];
    dynamicValidators: DynamicValidator[];
  }

  /**
   * Configuration options for creating a permission validator
   */
  export interface PermissionValidatorOptions {
    /**
     * Async function to retrieve the current session
     * Should return null/undefined if no session exists
     */
    getSession: () => Promise<Session | null | undefined>;

    /**
     * Async function to retrieve user claims
     * Receives the session object and should return claims object
     * @example
     * async (session) => ({
     *   role: ['business'],
     *   businessOwner: ['business-1', 'business-2']
     * })
     */
    getClaims: (session: Session) => Promise<Claims>;

    /**
     * Callback for handling unauthenticated users
     * Usually redirects to login page or returns 401 response
     */
    onUnauthenticated: () => void | Promise<void>;

    /**
     * Callback for handling unauthorized access
     * Usually redirects to home page or returns 403 response
     */
    onUnauthorized: () => void | Promise<void>;
  }

  /**
   * Result object returned by permission validator
   */
  export interface PermissionValidatorResult {
    session?: Session;
    claims?: Claims;
    status: 200 | 401 | 403;
  }

  /**
   * Interface for building access rules using a fluent API
   */
  export interface AccessRuleBuilder {
    /**
     * Adds a static condition to the access rule
     * @param key The condition key (e.g., 'role', 'department')
     * @param values One or more acceptable values for the condition
     * @throws {Error} If key is empty or no values are provided
     */
    addCondition(key: string, ...values: (string | number)[]): AccessRuleBuilder;

    /**
     * Adds a dynamic condition to the access rule
     * @param validator Function that performs dynamic validation
     * @throws {Error} If validator is not a function
     */
    addDynamicCondition(validator: DynamicValidator): AccessRuleBuilder;

    /**
     * Builds and returns the final rule object
     */
    build(): AccessRule;
  }

  /**
   * Creates a permission validator that combines authentication and authorization checks.
   * This factory function generates a validator that can be used to protect routes or resources.
   * 
   * @param options Configuration options
   * @returns An async validator function that accepts access rules and context
   * 
   * @example
   * // Basic usage with Next.js and static rules
   * const validatePermission = createPermissionValidator({
   *   getSession: auth,
   *   getClaims: async (session) => ({
   *     role: ['admin'],
   *     department: ['IT']
   *   }),
   *   onUnauthenticated: () => redirect('/auth/signin'),
   *   onUnauthorized: () => redirect('/')
   * });
   * 
   * @example
   * // Usage with dynamic business rules
   * const validatePermission = createPermissionValidator({
   *   getSession: auth,
   *   getClaims: async (session) => ({
   *     role: ['business'],
   *     businessOwner: ['business-1', 'business-2']
   *   }),
   *   onUnauthenticated: () => redirect('/auth/signin'),
   *   onUnauthorized: () => redirect('/')
   * });
   */
  export function createPermissionValidator(
    options: PermissionValidatorOptions
  ): (
    criteria: AccessRule[],
    context?: ValidationContext
  ) => Promise<PermissionValidatorResult>;

  /**
   * Validates user claims against a set of access rules using OR/AND logic.
   * Supports both static claim validation and dynamic resource-based validation.
   * 
   * @param accessRules Array of rule groups
   * @param userClaims Object containing user's claims
   * @param context Context object passed to dynamic validators
   * @throws {Error} If accessRules is not an array
   * @throws {Error} If user's claims don't match any rule group
   * @returns Returns true if validation passes
   */
  export function validateClaim(
    accessRules: AccessRule[],
    userClaims: Claims,
    context?: ValidationContext
  ): Promise<boolean>;

  /**
   * Creates an access rule builder for constructing authorization rules.
   * The builder follows a fluent interface pattern allowing method chaining
   * for creating complex access conditions.
   * 
   * @returns Rule builder object with methods for building access rules
   * 
   * @example
   * // Static only - single condition
   * const adminRule = createAccessRule()
   *   .addCondition('role', 'admin')
   *   .build();
   * 
   * @example
   * // Mixed - static and dynamic conditions
   * const complexRule = createAccessRule()
   *   .addCondition('role', 'business')
   *   .addDynamicCondition(({ claims, resources }) => {
   *     const businessIds = claims.businessOwner || [];
   *     return businessIds.includes(resources.business?.id);
   *   })
   *   .build();
   */
  export function createAccessRule(): AccessRuleBuilder;
}
