// Type definitions for mbkauthe
// Project: https://github.com/MIbnEKhalid/mbkauthe
// Definitions by: Muhammad Bin Khalid <https://github.com/MIbnEKhalid>

import { Request, Response, NextFunction, Router } from 'express';
import { Pool } from 'pg';

// Global augmentations must be at the top level, outside any declare module blocks
declare global {
  namespace Express {
    interface Request {
      user?: {
        username: string;
        role: 'SuperAdmin' | 'NormalUser' | 'Guest';
        fullname?: string;
      };
      userRole?: 'SuperAdmin' | 'NormalUser' | 'Guest';
    }

    interface Session {
      user?: {
        id: number;
        username: string;
        fullname?: string;
        role: 'SuperAdmin' | 'NormalUser' | 'Guest';
        sessionId?: string;
        allowedApps?: string[];
        tokenScope?: 'read-only' | 'write' | null;
      };
      preAuthUser?: {
        id: number;
        username: string;
        role: 'SuperAdmin' | 'NormalUser' | 'Guest';
        loginMethod?: 'password' | 'github' | 'google';
        redirectUrl?: string | null;
        allowedApps?: string[];
      };
      oauthRedirect?: string;
      oauthCsrfToken?: string;
      [key: string]: any;
    }
  }
}

declare module 'mbkauthe' {
  // Configuration Types
  export interface MBKAuthConfig {
    APP_NAME: string;
    SESSION_SECRET_KEY: string;
    Main_SECRET_TOKEN: string;
    IS_DEPLOYED: 'true' | 'false' | 'f';
    DOMAIN: string;
    LOGIN_DB: string;
    MBKAUTH_TWO_FA_ENABLE: 'true' | 'false' | 'f';
    COOKIE_EXPIRE_TIME?: number;
    DEVICE_TRUST_DURATION_DAYS?: number;
    GITHUB_LOGIN_ENABLED?: 'true' | 'false' | 'f';
    GITHUB_APP_SLUG?: string;
    GITHUB_APP_CLIENT_ID?: string;
    GITHUB_APP_CLIENT_SECRET?: string;
    GOOGLE_LOGIN_ENABLED?: 'true' | 'false' | 'f';
    GOOGLE_CLIENT_ID?: string;
    GOOGLE_CLIENT_SECRET?: string;
    loginRedirectURL?: string;
    MAX_SESSIONS_PER_USER?: number;
  }

  export interface OAuthConfig {
    GITHUB_LOGIN_ENABLED?: 'true' | 'false' | 'f';
    GITHUB_APP_SLUG?: string;
    GITHUB_APP_CLIENT_ID?: string;
    GITHUB_APP_CLIENT_SECRET?: string;
    GOOGLE_LOGIN_ENABLED?: 'true' | 'false' | 'f';
    GOOGLE_CLIENT_ID?: string;
    GOOGLE_CLIENT_SECRET?: string;
  }

  // User Types
  export type UserRole = 'SuperAdmin' | 'NormalUser' | 'Guest';

  export interface SessionUser {
    id: number;
    username: string;
    fullname?: string;
    role: UserRole;
    sessionId?: string;
    allowedApps?: string[];
  }

  export interface PreAuthUser {
    id: number;
    username: string;
    role: UserRole;
    allowedApps?: string[];
    loginMethod?: 'password' | 'github' | 'google';
    redirectUrl?: string | null;
  }

  // Database Types
  export interface DBUser {
    id: number;
    UserName: string;
    PasswordEnc?: string;
    Role: UserRole;
    Active: boolean;
    AllowedApps: string[];

    created_at?: Date;
    updated_at?: Date;
    last_login?: Date;
  }

  export interface TwoFARecord {
    UserName: string;
    TwoFAStatus: boolean;
    TwoFASecret?: string;
  }

  export interface TrustedDevice {
    id: number;
    UserName: string;
    DeviceToken: string;
    DeviceName?: string;
    UserAgent?: string;
    IpAddress?: string;
    CreatedAt: Date;
    ExpiresAt: Date;
    LastUsed: Date;
  }

  export interface GitHubUser {
    id: number;
    user_name: string;
    github_id: string;
    github_username: string;
    installation_id?: number;
    installation_target_type?: string;
    access_token: string;
    created_at: Date;
    updated_at: Date;
  }

  export interface GoogleUser {
    id: number;
    user_name: string;
    google_id: string;
    google_email: string;
    access_token: string;
    created_at: Date;
    updated_at: Date;
  }

  // API Token Types
  export type TokenScope = 'read-only' | 'write';
  
  export interface TokenPermissions {
    scope: TokenScope;
    allowedApps: string[] | null;
  }

  export interface ApiToken {
    id: number;
    UserName: string;
    Name: string;
    TokenHash: string;
    Prefix: string;
    Permissions: TokenPermissions;
    LastUsed?: Date;
    CreatedAt: Date;
    ExpiresAt?: Date;
  }

  // API Response Types
  export interface LoginResponse {
    success: boolean;
    message: string;
    sessionId?: string;
    twoFactorRequired?: boolean;
    redirectUrl?: string;
    errorCode?: number;
  }

  export interface LogoutResponse {
    success: boolean;
    message: string;
  }

  export interface TwoFAVerifyResponse {
    success: boolean;
    message: string;
    sessionId?: string;
    redirectUrl?: string;
  }

  export interface ErrorResponse {
    success: false;
    message: string;
    errorCode?: number;
  }

  // Error Render Options
  export interface ErrorRenderOptions {
    layout?: boolean;
    code: number | string;
    error: string;
    message: string;
    page?: string;
    pagename?: string;
    details?: string;
    app?: string;
    version?: string;
  }

  // Middleware Types
  export type AuthMiddleware = (
    req: Request,
    res: Response,
    next: NextFunction
  ) => void | Promise<void>;

  // Middleware Functions
  export function validateSession(
    req: Request,
    res: Response,
    next: NextFunction
  ): void | Promise<void>;

  export function validateApiSession(
    req: Request,
    res: Response,
    next: NextFunction
  ): void | Promise<void>;

  export function checkRolePermission(
    requiredRole: UserRole | 'Any' | 'any',
    notAllowed?: UserRole
  ): AuthMiddleware;

  export function validateSessionAndRole(
    requiredRole: UserRole | 'Any' | 'any',
    notAllowed?: UserRole
  ): AuthMiddleware;

  export const sessVal: AuthMiddleware;
  export const sessRole: AuthMiddleware;

  export const strictValidateSession: AuthMiddleware;

  export function strictValidateSessionAndRole(
    requiredRole: UserRole | 'Any' | 'any',
    notAllowed?: UserRole
  ): AuthMiddleware;

  export function authenticate(token: string): AuthMiddleware;

  // Reload session user values from DB and refresh cookies.
  // Returns true when session is refreshed and valid, false if session invalidated.
  export function reloadSessionUser(req: Request, res: Response): Promise<boolean>;

  // Utility Functions
  // Renders an error page — signature is (res, req, options)
  export function renderError(
    res: Response,
    req: Request,
    options: ErrorRenderOptions
  ): Response;

  // Return a lightweight context object used to populate templates
  export function getUserContext(req: Request): {
    userLoggedIn: boolean;
    isuserlogin: boolean;
    username: string;
    fullname: string;
    role: string;
    allowedApps: string[];
  };

  // Renders a template page with optional layout and data
  export function renderPage(
    req: Request,
    res: Response,
    fileLocation: string,
    layout?: boolean,
    data?: Record<string, any>
  ): Promise<Response>;

  // Error utilities
  export const ErrorCodes: { [key: string]: number };
  export const ErrorMessages: { [key: number]: { message: string; userMessage?: string; hint?: string } };
  export function getErrorByCode(errorCode: number, customData?: any): { errorCode: number; message: string; userMessage?: string; hint?: string } & any;
  export function createErrorResponse(statusCode: number, errorCode: number, customData?: any): any;
  export function logError(context: string, errorCode: number, additionalInfo?: any): void;

  export function getCookieOptions(): {
    maxAge: number;
    domain?: string;
    secure: boolean;
    sameSite: 'lax';
    path: string;
    httpOnly: boolean;
  };

  export function getClearCookieOptions(): {
    domain?: string;
    secure: boolean;
    sameSite: 'lax';
    path: string;
    httpOnly: boolean;
  };

  export function generateDeviceToken(): string;

  export function getDeviceTokenCookieOptions(): {
    maxAge: number;
    domain?: string;
    secure: boolean;
    sameSite: 'lax';
    path: string;
    httpOnly: boolean;
  };

  export function hashPassword(password: string, username: string): string;

  export function clearSessionCookies(res: Response): void;

  export function getLatestVersion(): Promise<string>;

  // Exports
  export const dblogin: Pool;
  export const mbkautheVar: MBKAuthConfig;
  export const cachedCookieOptions: ReturnType<typeof getCookieOptions>;
  export const cachedClearCookieOptions: ReturnType<typeof getClearCookieOptions>;
  export const packageJson: { version: string; [key: string]: any };
  export const appVersion: string;
  export const DEVICE_TRUST_DURATION_DAYS: number;
  export const DEVICE_TRUST_DURATION_MS: number;

  // Default Export (Express Router)
  const router: Router;
  export default router;
}
