/**
 * Token Authentication
 *
 * 简单的 Token 认证机制
 * - 本地模式 (127.0.0.1): 无需认证
 * - 远程模式: 需要 Bearer Token
 */

import { createMiddleware } from 'hono/factory';
import type { Context, Next } from 'hono';

// ============================================================================
// 类型定义
// ============================================================================

export interface AuthConfig {
  /** 是否启用认证 (远程模式下自动启用) */
  enabled: boolean;
  /** 有效的 token 列表 */
  tokens: string[];
  /** 跳过认证的路径 */
  skipPaths: string[];
}

export interface AuthContext {
  /** 是否已认证 */
  authenticated: boolean;
  /** 使用的 token (脱敏) */
  tokenHint?: string;
}

// ============================================================================
// 默认配置
// ============================================================================

const defaultConfig: AuthConfig = {
  enabled: false,
  tokens: [],
  skipPaths: ['/health', '/api/health'],
};

// 当前配置
let authConfig: AuthConfig = { ...defaultConfig };

// ============================================================================
// Token 生成
// ============================================================================

/**
 * 生成随机 token
 */
export function generateToken(length: number = 32): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let token = '';
  const randomValues = new Uint8Array(length);
  crypto.getRandomValues(randomValues);
  for (let i = 0; i < length; i++) {
    token += chars[randomValues[i] % chars.length];
  }
  return token;
}

/**
 * 脱敏 token (只显示前4位和后4位)
 */
export function maskToken(token: string): string {
  if (token.length <= 8) {
    return '****';
  }
  return `${token.slice(0, 4)}...${token.slice(-4)}`;
}

// ============================================================================
// 配置管理
// ============================================================================

/**
 * 初始化认证配置
 */
export function initAuth(config: Partial<AuthConfig> = {}): AuthConfig {
  authConfig = {
    ...defaultConfig,
    ...config,
  };
  return authConfig;
}

/**
 * 获取认证配置
 */
export function getAuthConfig(): AuthConfig {
  return { ...authConfig };
}

/**
 * 添加 token
 */
export function addToken(token: string): void {
  if (!authConfig.tokens.includes(token)) {
    authConfig.tokens.push(token);
  }
}

/**
 * 移除 token
 */
export function removeToken(token: string): void {
  const index = authConfig.tokens.indexOf(token);
  if (index !== -1) {
    authConfig.tokens.splice(index, 1);
  }
}

/**
 * 启用/禁用认证
 */
export function setAuthEnabled(enabled: boolean): void {
  authConfig.enabled = enabled;
}

/**
 * 检查是否为本地请求
 */
function isLocalRequest(c: Context): boolean {
  // 获取客户端 IP
  const forwarded = c.req.header('x-forwarded-for');
  const realIp = c.req.header('x-real-ip');

  // 如果有代理头，检查原始 IP
  if (forwarded) {
    const clientIp = forwarded.split(',')[0].trim();
    return isLocalIP(clientIp);
  }

  if (realIp) {
    return isLocalIP(realIp);
  }

  // Bun/Hono 环境下获取连接 IP
  // 这需要 server 层传递，目前假设本地
  return true;
}

/**
 * 检查是否为本地 IP
 */
function isLocalIP(ip: string): boolean {
  return (
    ip === '127.0.0.1' ||
    ip === '::1' ||
    ip === 'localhost' ||
    ip.startsWith('192.168.') ||
    ip.startsWith('10.') ||
    ip.startsWith('172.16.') ||
    ip.startsWith('172.17.') ||
    ip.startsWith('172.18.') ||
    ip.startsWith('172.19.') ||
    ip.startsWith('172.2') ||
    ip.startsWith('172.30.') ||
    ip.startsWith('172.31.')
  );
}

// ============================================================================
// 认证验证
// ============================================================================

/**
 * 验证 token
 */
export function validateToken(token: string): boolean {
  return authConfig.tokens.includes(token);
}

/**
 * 从请求中提取 token
 */
export function extractToken(c: Context): string | null {
  // 1. 从 Authorization header 提取
  const authHeader = c.req.header('Authorization');
  if (authHeader?.startsWith('Bearer ')) {
    return authHeader.slice(7);
  }

  // 2. 从 query parameter 提取 (用于 WebSocket)
  const queryToken = c.req.query('token');
  if (queryToken) {
    return queryToken;
  }

  return null;
}

// ============================================================================
// Hono 中间件
// ============================================================================

/**
 * 认证中间件
 */
export const authMiddleware = createMiddleware(async (c: Context, next: Next) => {
  // 检查是否跳过认证
  const path = c.req.path;
  if (authConfig.skipPaths.some((p) => path.startsWith(p))) {
    await next();
    return;
  }

  // 如果认证未启用，跳过
  if (!authConfig.enabled) {
    c.set('auth', { authenticated: true } as AuthContext);
    await next();
    return;
  }

  // 本地请求跳过认证
  if (isLocalRequest(c)) {
    c.set('auth', { authenticated: true } as AuthContext);
    await next();
    return;
  }

  // 提取 token
  const token = extractToken(c);

  if (!token) {
    return c.json(
      {
        success: false,
        error: 'Authentication required',
        message: 'Please provide a valid token in the Authorization header',
      },
      401
    );
  }

  // 验证 token
  if (!validateToken(token)) {
    return c.json(
      {
        success: false,
        error: 'Invalid token',
        message: 'The provided token is not valid',
      },
      401
    );
  }

  // 设置认证上下文
  c.set('auth', {
    authenticated: true,
    tokenHint: maskToken(token),
  } as AuthContext);

  await next();
});

/**
 * 获取当前请求的认证上下文
 */
export function getAuthContext(c: Context): AuthContext {
  return c.get('auth') || { authenticated: false };
}
