/**
 * Project Context Builder
 * 
 * Builds a generic project context summary for AI validation by analyzing
 * common patterns across the codebase. This context helps the AI validator
 * understand the project's security architecture without hardcoding any
 * specific framework or vendor.
 * 
 * Key areas analyzed:
 * - Authentication & access control patterns
 * - Data access patterns (ORMs, query builders, raw queries)
 * - Secrets & configuration handling
 * - Framework detection
 */

import type { ScanFile } from '../shared/types'
import { detectGlobalAuthMiddleware, detectUserScopingPatterns, type MiddlewareAuthConfig } from './middleware-detector'
import { detectAuthHelpers, type AuthHelperContext, type AuthHelper } from './auth-helper-detector'
import { detectOAuthFlow, isOAuthStateImplemented, getOAuthFlowSummary, type OAuthFlowContext } from './oauth-flow-detector'
import { analyzeTRPCRouters, getTRPCSummary, type TRPCRouterContext } from './trpc-analyzer'

// ============================================================================
// Types
// ============================================================================

export interface ProjectContext {
  /** Summary string for AI prompt injection */
  summary: string
  
  /** Authentication & access control patterns */
  auth: AuthContext
  
  /** Data access patterns */
  dataAccess: DataAccessContext
  
  /** Secrets & configuration patterns */
  secrets: SecretsContext
  
  /** Detected frameworks and libraries */
  frameworks: FrameworkContext
  
  /** File structure insights */
  structure: StructureContext

  /** OAuth flow context */
  oauth: OAuthFlowContext

  /** tRPC router context */
  trpc: TRPCRouterContext
}

export interface AuthContext {
  /** Whether global auth middleware is detected */
  hasGlobalMiddleware: boolean
  /** Type of auth provider (clerk, nextauth, auth0, custom, unknown) */
  authProvider?: string
  /** Middleware file path */
  middlewareFile?: string
  /** Protected path patterns */
  protectedPaths: string[]
  /** Public/excluded path patterns */
  publicPaths: string[]
  /** Auth helper functions detected (names only) */
  authHelpers: string[]
  /** Full auth helper context with throwing/return info */
  authHelperContext?: AuthHelperContext
  /** Throwing auth helpers that guarantee authenticated context */
  throwingAuthHelpers: AuthHelper[]
  /** Whether user scoping is used in queries */
  hasUserScoping: boolean
  /** User scoping patterns found */
  userScopingPatterns: string[]
}

export interface DataAccessContext {
  /** ORM/query builder detected */
  orm?: 'prisma' | 'drizzle' | 'supabase' | 'mongoose' | 'sequelize' | 'typeorm' | 'knex' | 'raw_sql' | 'unknown'
  /** Whether parameterized queries are the default */
  usesParameterizedQueries: boolean
  /** Database type if detectable */
  databaseType?: 'postgres' | 'mysql' | 'mongodb' | 'sqlite' | 'unknown'
  /** Whether RLS (Row Level Security) is mentioned */
  hasRLS: boolean
  /** Data validation library detected */
  validationLibrary?: string
}

export interface SecretsContext {
  /** Uses environment variables for secrets */
  usesEnvVars: boolean
  /** Uses a secret manager */
  usesSecretManager: boolean
  /** Secret manager type if detected */
  secretManagerType?: string
  /** Has .env files */
  hasEnvFiles: boolean
  /** Uses NEXT_PUBLIC_ pattern (client-exposed) */
  hasClientExposedEnvVars: boolean
}

export interface FrameworkContext {
  /** Primary framework */
  primary?: 'nextjs' | 'express' | 'fastify' | 'nestjs' | 'django' | 'flask' | 'rails' | 'unknown'
  /** Frontend framework */
  frontend?: 'react' | 'vue' | 'svelte' | 'angular' | 'unknown'
  /** Is this a monorepo? */
  isMonorepo: boolean
  /** Uses TypeScript */
  usesTypeScript: boolean
  /** Uses server components (Next.js 13+) */
  usesServerComponents: boolean
  /** Uses server actions */
  usesServerActions: boolean
}

export interface StructureContext {
  /** Has API routes */
  hasApiRoutes: boolean
  /** Has middleware */
  hasMiddleware: boolean
  /** Has server actions */
  hasServerActions: boolean
  /** Total files analyzed */
  totalFiles: number
  /** File types breakdown */
  fileTypes: Record<string, number>
}

// ============================================================================
// Pattern Definitions
// ============================================================================

const AUTH_HELPER_PATTERNS = [
  { pattern: /getCurrentUser|getUser|fetchUser/i, name: 'getCurrentUser' },
  { pattern: /getCurrentUserId|getUserId/i, name: 'getCurrentUserId' },
  { pattern: /getSession|getServerSession/i, name: 'getSession' },
  { pattern: /requireAuth|ensureAuth|checkAuth/i, name: 'requireAuth' },
  { pattern: /verifyToken|validateToken/i, name: 'verifyToken' },
  { pattern: /isAuthenticated|isLoggedIn/i, name: 'isAuthenticated' },
  { pattern: /withAuth|authGuard/i, name: 'withAuth' },
  { pattern: /useAuth|useSession/i, name: 'useAuth (hook)' },
  { pattern: /auth\(\)|getAuth\(\)/i, name: 'auth()' },
]

const ORM_PATTERNS = [
  { pattern: /from\s+['"]@prisma\/client['"]|PrismaClient/i, orm: 'prisma' as const },
  { pattern: /from\s+['"]drizzle-orm['"]|drizzle\(/i, orm: 'drizzle' as const },
  { pattern: /from\s+['"]@supabase\/supabase-js['"]|createClient.*supabase/i, orm: 'supabase' as const },
  { pattern: /from\s+['"]mongoose['"]|mongoose\.connect/i, orm: 'mongoose' as const },
  { pattern: /from\s+['"]sequelize['"]|Sequelize/i, orm: 'sequelize' as const },
  { pattern: /from\s+['"]typeorm['"]|DataSource/i, orm: 'typeorm' as const },
  { pattern: /from\s+['"]knex['"]|knex\(/i, orm: 'knex' as const },
]

const VALIDATION_LIBRARY_PATTERNS = [
  { pattern: /from\s+['"]zod['"]|z\.object/i, lib: 'zod' },
  { pattern: /from\s+['"]yup['"]|yup\.object/i, lib: 'yup' },
  { pattern: /from\s+['"]joi['"]|Joi\.object/i, lib: 'joi' },
  { pattern: /from\s+['"]valibot['"]|v\.object/i, lib: 'valibot' },
  { pattern: /from\s+['"]class-validator['"]|@IsString|@IsEmail/i, lib: 'class-validator' },
]

const SECRET_MANAGER_PATTERNS = [
  { pattern: /aws-sdk.*secretsmanager|SecretsManager/i, type: 'AWS Secrets Manager' },
  { pattern: /google-cloud.*secret-manager|SecretManagerServiceClient/i, type: 'Google Secret Manager' },
  { pattern: /@azure\/keyvault|KeyVaultSecret/i, type: 'Azure Key Vault' },
  { pattern: /hashicorp.*vault|vault\.read/i, type: 'HashiCorp Vault' },
  { pattern: /doppler|infisical/i, type: 'Doppler/Infisical' },
]

// ============================================================================
// Main Builder Function
// ============================================================================

/**
 * Build a comprehensive project context from scanned files
 * This context is used to inform AI validation decisions
 */
export function buildProjectContext(files: ScanFile[]): ProjectContext {
  // Detect middleware configuration
  const middlewareConfig = detectGlobalAuthMiddleware(files)
  
  // Build individual context sections
  const auth = buildAuthContext(files, middlewareConfig)
  const dataAccess = buildDataAccessContext(files)
  const secrets = buildSecretsContext(files)
  const frameworks = buildFrameworkContext(files)
  const structure = buildStructureContext(files)
  const oauth = detectOAuthFlow(files)
  const trpc = analyzeTRPCRouters(files)
  
  // Generate summary string for AI prompt
  const summary = generateContextSummary({
    auth,
    dataAccess,
    secrets,
    frameworks,
    structure,
    oauth,
    trpc,
  })
  
  return {
    summary,
    auth,
    dataAccess,
    secrets,
    frameworks,
    structure,
    oauth,
    trpc,
  }
}

// ============================================================================
// Context Builders
// ============================================================================

function buildAuthContext(files: ScanFile[], middlewareConfig: MiddlewareAuthConfig): AuthContext {
  const authHelperNames: string[] = []
  let hasUserScoping = false
  const userScopingPatterns: string[] = []
  
  // Detect auth helpers using the dedicated detector (includes throwing detection)
  const authHelperContext = detectAuthHelpers(files)
  const throwingAuthHelpers = authHelperContext.helpers.filter(h => h.throwsOnMissing)
  
  // Scan all files for additional auth patterns and user scoping
  for (const file of files) {
    // Skip non-code files
    if (!isCodeFile(file.path)) continue
    
    // Detect auth helper functions by name patterns
    for (const { pattern, name } of AUTH_HELPER_PATTERNS) {
      if (pattern.test(file.content) && !authHelperNames.includes(name)) {
        authHelperNames.push(name)
      }
    }
    
    // Detect user scoping patterns
    const scoping = detectUserScopingPatterns(file.content)
    if (scoping.hasUserScoping) {
      hasUserScoping = true
      for (const p of scoping.patterns) {
        if (!userScopingPatterns.includes(p)) {
          userScopingPatterns.push(p)
        }
      }
    }
  }
  
  // Merge detected helper names from both sources
  for (const helper of authHelperContext.helpers) {
    if (!authHelperNames.includes(helper.name)) {
      authHelperNames.push(helper.name)
    }
  }
  
  return {
    hasGlobalMiddleware: middlewareConfig.hasAuthMiddleware,
    authProvider: middlewareConfig.authType,
    middlewareFile: middlewareConfig.middlewareFile,
    protectedPaths: middlewareConfig.protectedPaths,
    publicPaths: middlewareConfig.publicPaths,
    authHelpers: authHelperNames,
    authHelperContext,
    throwingAuthHelpers,
    hasUserScoping,
    userScopingPatterns,
  }
}

function buildDataAccessContext(files: ScanFile[]): DataAccessContext {
  let orm: DataAccessContext['orm'] = undefined
  let usesParameterizedQueries = false
  let databaseType: DataAccessContext['databaseType'] = undefined
  let hasRLS = false
  let validationLibrary: string | undefined = undefined
  
  for (const file of files) {
    if (!isCodeFile(file.path)) continue
    const content = file.content
    
    // Detect ORM
    if (!orm) {
      for (const { pattern, orm: ormType } of ORM_PATTERNS) {
        if (pattern.test(content)) {
          orm = ormType
          break
        }
      }
    }
    
    // Detect parameterized queries
    if (!usesParameterizedQueries) {
      // Prisma, Drizzle, Supabase all use parameterized by default
      if (orm === 'prisma' || orm === 'drizzle' || orm === 'supabase') {
        usesParameterizedQueries = true
      }
      // Check for explicit parameterized patterns
      if (/\$\d+|\?\s*,|\?(?=\s*\))|:[\w]+/i.test(content) && /query|execute|sql/i.test(content)) {
        usesParameterizedQueries = true
      }
    }
    
    // Detect database type
    if (!databaseType) {
      if (/postgres|pg\.|@vercel\/postgres/i.test(content)) {
        databaseType = 'postgres'
      } else if (/mysql|mysql2/i.test(content)) {
        databaseType = 'mysql'
      } else if (/mongodb|mongoose/i.test(content)) {
        databaseType = 'mongodb'
      } else if (/sqlite|better-sqlite/i.test(content)) {
        databaseType = 'sqlite'
      }
    }
    
    // Detect RLS
    if (!hasRLS && /row.?level.?security|RLS|\.rls\(|enable_rls/i.test(content)) {
      hasRLS = true
    }
    
    // Detect validation library
    if (!validationLibrary) {
      for (const { pattern, lib } of VALIDATION_LIBRARY_PATTERNS) {
        if (pattern.test(content)) {
          validationLibrary = lib
          break
        }
      }
    }
  }
  
  // If no ORM detected but SQL patterns found, mark as raw_sql
  if (!orm) {
    const hasRawSql = files.some(f => 
      /SELECT\s+.*FROM|INSERT\s+INTO|UPDATE\s+.*SET|DELETE\s+FROM/i.test(f.content)
    )
    if (hasRawSql) {
      orm = 'raw_sql'
    }
  }
  
  return {
    orm,
    usesParameterizedQueries,
    databaseType,
    hasRLS,
    validationLibrary,
  }
}

function buildSecretsContext(files: ScanFile[]): SecretsContext {
  let usesEnvVars = false
  let usesSecretManager = false
  let secretManagerType: string | undefined = undefined
  let hasEnvFiles = false
  let hasClientExposedEnvVars = false
  
  for (const file of files) {
    // Check for .env files
    if (file.path.includes('.env')) {
      hasEnvFiles = true
    }
    
    // Check for env var usage
    if (/process\.env\.|import\.meta\.env\.|Deno\.env/i.test(file.content)) {
      usesEnvVars = true
    }
    
    // Check for NEXT_PUBLIC_ pattern
    if (/NEXT_PUBLIC_/i.test(file.content)) {
      hasClientExposedEnvVars = true
    }
    
    // Check for secret managers
    if (!usesSecretManager) {
      for (const { pattern, type } of SECRET_MANAGER_PATTERNS) {
        if (pattern.test(file.content)) {
          usesSecretManager = true
          secretManagerType = type
          break
        }
      }
    }
  }
  
  return {
    usesEnvVars,
    usesSecretManager,
    secretManagerType,
    hasEnvFiles,
    hasClientExposedEnvVars,
  }
}

function buildFrameworkContext(files: ScanFile[]): FrameworkContext {
  let primary: FrameworkContext['primary'] = undefined
  let frontend: FrameworkContext['frontend'] = undefined
  let isMonorepo = false
  let usesTypeScript = false
  let usesServerComponents = false
  let usesServerActions = false
  
  // Check for package.json to detect frameworks
  const packageJson = files.find(f => f.path === 'package.json' || f.path.endsWith('/package.json'))
  if (packageJson) {
    const content = packageJson.content
    
    // Primary framework detection
    if (/["']next["']/i.test(content)) {
      primary = 'nextjs'
    } else if (/["']express["']/i.test(content)) {
      primary = 'express'
    } else if (/["']fastify["']/i.test(content)) {
      primary = 'fastify'
    } else if (/["']@nestjs\/core["']/i.test(content)) {
      primary = 'nestjs'
    }
    
    // Frontend framework detection
    if (/["']react["']/i.test(content)) {
      frontend = 'react'
    } else if (/["']vue["']/i.test(content)) {
      frontend = 'vue'
    } else if (/["']svelte["']/i.test(content)) {
      frontend = 'svelte'
    } else if (/["']@angular\/core["']/i.test(content)) {
      frontend = 'angular'
    }
    
    // Monorepo detection
    if (/["']workspaces["']|turbo\.json|lerna\.json|pnpm-workspace/i.test(content)) {
      isMonorepo = true
    }
  }
  
  // Check for TypeScript
  usesTypeScript = files.some(f => f.path.endsWith('.ts') || f.path.endsWith('.tsx'))
  
  // Check for Next.js 13+ patterns
  for (const file of files) {
    if (/['"]use server['"]/.test(file.content)) {
      usesServerActions = true
    }
    if (/['"]use client['"]/.test(file.content) || file.path.includes('/app/')) {
      usesServerComponents = true // App Router implies server components
    }
  }
  
  return {
    primary,
    frontend,
    isMonorepo,
    usesTypeScript,
    usesServerComponents,
    usesServerActions,
  }
}

function buildStructureContext(files: ScanFile[]): StructureContext {
  const fileTypes: Record<string, number> = {}
  let hasApiRoutes = false
  let hasMiddleware = false
  let hasServerActions = false
  
  for (const file of files) {
    // Count file types
    const ext = getFileExtension(file.path)
    fileTypes[ext] = (fileTypes[ext] || 0) + 1
    
    // Check for API routes
    if (/\/api\/|route\.(ts|js)$|\/routes\//i.test(file.path)) {
      hasApiRoutes = true
    }
    
    // Check for middleware
    if (/middleware\.(ts|js)$/i.test(file.path)) {
      hasMiddleware = true
    }
    
    // Check for server actions
    if (/\/actions\/|\.action\.(ts|js)$/i.test(file.path) || /['"]use server['"]/.test(file.content)) {
      hasServerActions = true
    }
  }
  
  return {
    hasApiRoutes,
    hasMiddleware,
    hasServerActions,
    totalFiles: files.length,
    fileTypes,
  }
}

// ============================================================================
// Summary Generator
// ============================================================================

function generateContextSummary(ctx: Omit<ProjectContext, 'summary'>): string {
  const lines: string[] = []
  
  lines.push('## Project Security Context')
  lines.push('')
  
  // Framework info
  if (ctx.frameworks.primary) {
    lines.push(`**Framework:** ${ctx.frameworks.primary}${ctx.frameworks.frontend ? ` + ${ctx.frameworks.frontend}` : ''}`)
  }
  if (ctx.frameworks.usesTypeScript) {
    lines.push('**Language:** TypeScript')
  }
  if (ctx.frameworks.usesServerComponents || ctx.frameworks.usesServerActions) {
    lines.push(`**Patterns:** ${[
      ctx.frameworks.usesServerComponents && 'Server Components',
      ctx.frameworks.usesServerActions && 'Server Actions',
    ].filter(Boolean).join(', ')}`)
  }
  lines.push('')
  
  // Auth info
  lines.push('### Authentication & Access Control')
  if (ctx.auth.hasGlobalMiddleware) {
    lines.push(`- **Global auth middleware detected** (${ctx.auth.authProvider || 'custom'})`)
    if (ctx.auth.middlewareFile) {
      lines.push(`  - Middleware file: \`${ctx.auth.middlewareFile}\``)
    }
    if (ctx.auth.protectedPaths.length > 0) {
      lines.push(`  - Protected paths: ${ctx.auth.protectedPaths.join(', ')}`)
    }
    if (ctx.auth.publicPaths.length > 0) {
      lines.push(`  - Public paths: ${ctx.auth.publicPaths.join(', ')}`)
    }
  } else {
    lines.push('- No global auth middleware detected')
  }
  
  if (ctx.auth.authHelpers.length > 0) {
    lines.push(`- **Auth helpers found:** ${ctx.auth.authHelpers.join(', ')}`)
  }
  
  // Throwing auth helpers - CRITICAL for AI validation
  if (ctx.auth.throwingAuthHelpers && ctx.auth.throwingAuthHelpers.length > 0) {
    lines.push('- **Throwing auth helpers detected** (these GUARANTEE authenticated context):')
    for (const helper of ctx.auth.throwingAuthHelpers) {
      const location = helper.definedIn ? ` (in ${helper.definedIn})` : ''
      lines.push(`  - \`${helper.name}()\`${location} - throws/redirects on missing auth`)
    }
    lines.push('  - Code AFTER these calls is guaranteed to have an authenticated user')
    lines.push('  - Do NOT flag "missing auth" or suggest `if (!userId)` checks after these calls')
  }
  
  if (ctx.auth.hasUserScoping) {
    lines.push('- **User scoping detected** in database queries (data is filtered by user/tenant ID)')
  }
  lines.push('')
  
  // Data access info
  lines.push('### Data Access')
  if (ctx.dataAccess.orm) {
    lines.push(`- **ORM/Query Builder:** ${ctx.dataAccess.orm}`)
    if (ctx.dataAccess.usesParameterizedQueries) {
      lines.push('  - Uses parameterized queries by default (SQL injection protection)')
    }
  }
  if (ctx.dataAccess.databaseType) {
    lines.push(`- **Database:** ${ctx.dataAccess.databaseType}`)
  }
  if (ctx.dataAccess.hasRLS) {
    lines.push('- **Row Level Security (RLS)** is enabled')
  }
  if (ctx.dataAccess.validationLibrary) {
    lines.push(`- **Input validation:** ${ctx.dataAccess.validationLibrary}`)
  }
  lines.push('')
  
  // Secrets info
  lines.push('### Secrets & Configuration')
  if (ctx.secrets.usesEnvVars) {
    lines.push('- Uses environment variables for configuration')
  }
  if (ctx.secrets.usesSecretManager) {
    lines.push(`- Uses secret manager: ${ctx.secrets.secretManagerType}`)
  }
  if (ctx.secrets.hasClientExposedEnvVars) {
    lines.push('- Has NEXT_PUBLIC_ env vars (intentionally client-exposed)')
  }
  lines.push('')
  
  // Validation guidance
  lines.push('### Validation Guidance')
  lines.push('Based on this context:')
  
  if (ctx.auth.hasGlobalMiddleware) {
    lines.push(`- Routes under protected paths are guarded by ${ctx.auth.authProvider || 'auth'} middleware`)
    lines.push('- Downgrade "missing auth" findings for routes covered by middleware')
  }
  
  if (ctx.auth.throwingAuthHelpers && ctx.auth.throwingAuthHelpers.length > 0) {
    lines.push('- Throwing auth helpers provide guaranteed auth context - do NOT suggest redundant null checks')
  }
  
  if (ctx.auth.hasUserScoping) {
    lines.push('- Database queries are scoped by user ID - cross-tenant access is mitigated')
  }
  
  if (ctx.dataAccess.usesParameterizedQueries) {
    lines.push('- SQL injection risk is low due to parameterized queries')
  }
  
  if (ctx.dataAccess.hasRLS) {
    lines.push('- RLS provides database-level access control')
  }

  // OAuth flow context
  if (ctx.oauth && (ctx.oauth.hasStateGeneration || ctx.oauth.hasStateValidation || ctx.oauth.hasCodeVerifier)) {
    lines.push('')
    lines.push('### OAuth Flow')
    if (isOAuthStateImplemented(ctx.oauth)) {
      lines.push('- **OAuth state is properly implemented** across files')
      if (ctx.oauth.stateGenerationFile) {
        lines.push(`  - State generated in: \`${ctx.oauth.stateGenerationFile}\``)
      }
      if (ctx.oauth.stateValidationFile) {
        lines.push(`  - State validated in: \`${ctx.oauth.stateValidationFile}\``)
      }
      lines.push('- Do NOT flag "OAuth state missing" - it is implemented correctly')
    } else if (ctx.oauth.flowType === 'client_credentials') {
      lines.push('- **Client credentials flow detected** - no state parameter needed')
    } else if (ctx.oauth.hasCodeVerifier) {
      lines.push('- **PKCE flow detected** - code_verifier provides CSRF protection')
    }
    if (ctx.oauth.providers.length > 0) {
      lines.push(`- OAuth providers: ${ctx.oauth.providers.join(', ')}`)
    }
  }

  // tRPC context
  if (ctx.trpc && ctx.trpc.hasTRPC) {
    lines.push('')
    lines.push('### tRPC')
    lines.push(`- ${getTRPCSummary(ctx.trpc)}`)
    
    const protectedRouters = Array.from(ctx.trpc.routers.values()).filter(r => r.isProtected)
    if (protectedRouters.length > 0) {
      lines.push('- **Protected tRPC routers detected:**')
      for (const router of protectedRouters) {
        lines.push(`  - \`${router.name}\` router is protected by auth middleware`)
      }
      lines.push('- Frontend calls to protected tRPC procedures are SAFE - backend handles auth')
      lines.push('- Do NOT flag "missing role check" on frontend components calling protected tRPC procedures')
    }
  }
  
  return lines.join('\n')
}

// ============================================================================
// Helpers
// ============================================================================

function isCodeFile(path: string): boolean {
  return /\.(ts|tsx|js|jsx|mjs|cjs|py|rb|php|go|java|cs)$/i.test(path)
}

function getFileExtension(path: string): string {
  const match = path.match(/\.([^.]+)$/)
  return match ? `.${match[1]}` : 'unknown'
}

/**
 * Generate a compact context string for a single file validation
 * Used when validating findings in a specific file
 */
export function getFileValidationContext(
  file: ScanFile,
  projectContext: ProjectContext
): string {
  const lines: string[] = []
  
  // Include relevant project context
  lines.push(projectContext.summary)
  lines.push('')
  
  // Add file-specific context
  lines.push(`### Current File: \`${file.path}\``)
  
  // Determine if this file is server-only
  const isServerFile = /\/api\/|\/server\/|\.server\.|\/actions\/|route\.(ts|js)$|middleware\.(ts|js)$/i.test(file.path)
  if (isServerFile) {
    lines.push('- This is a **server-only** file (not bundled to client)')
  }
  
  // Check if file is under protected routes
  if (projectContext.auth.hasGlobalMiddleware) {
    const isProtected = projectContext.auth.protectedPaths.some(p => 
      file.path.includes(p.replace(/\*\*/g, '').replace(/\*/g, ''))
    )
    if (isProtected) {
      lines.push(`- This route is **protected by ${projectContext.auth.authProvider || 'auth'} middleware**`)
    }
  }
  
  return lines.join('\n')
}
