import { NextRequest, NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt';
import bcrypt from 'bcryptjs';
import { hasPermission } from './permissions';
import { PermissionCheck } from './types';
import { VOCAB } from '@/lib/white-label/constants';

export interface ApiContext {
  userId: string;
  email: string;
  roles: string[];
  permissions: string[];
  department?: string;
}

/**
 * Validates Basic Auth credentials against environment variables
 * Uses bcrypt for secure password comparison
 */
async function validateBasicAuth(username: string, password: string): Promise<boolean> {
  const expectedUsername = process.env.API_AUTH_USERNAME;
  const expectedPasswordHash = process.env.API_AUTH_PASSWORD_HASH;
  
  // Both must be configured
  if (!expectedUsername || !expectedPasswordHash) {
    console.warn('[API Guard] Basic Auth not configured - API_AUTH_USERNAME and API_AUTH_PASSWORD_HASH env vars required');
    return false;
  }
  
  // Basic username check (bcrypt provides timing-safe comparison for password)
  if (username !== expectedUsername) {
    return false;
  }
  
  // Bcrypt comparison (already timing-safe)
  return bcrypt.compare(password, expectedPasswordHash);
}

/**
 * Validates the ${VOCAB.controlPanel} session token
 * Uses secure comparison against environment variable
 */
function validateGhostControlToken(token: string): boolean {
  const expectedToken = process.env.GC_AUTH_TOKEN;
  
  if (!expectedToken) {
    console.warn(`[API Guard] ${VOCAB.controlPanel} token not configured - GC_AUTH_TOKEN env var required`);
    return false;
  }
  
  // Simple comparison - token should be a secure random value
  return token === expectedToken;
}

/**
 * API route guard that checks authentication and permissions
 * Returns user context if authorized, or an error response
 */
export async function withPermission(
  request: NextRequest,
  check: PermissionCheck
): Promise<ApiContext | NextResponse> {
  // Check for ${VOCAB.controlPanel} session cookie first (set by middleware for admin access)
  const gcAuthCookie = request.cookies.get('gc_auth_token')?.value;
  if (gcAuthCookie && validateGhostControlToken(gcAuthCookie)) {
    return {
      userId: 'gc-session',
      email: 'admin@ghostfoundry.ai',
      roles: ['super_admin'],
      permissions: ['system:admin:all'],
    };
  }

  // Check for NextAuth token
  const token = await getToken({
    req: request,
    secret: process.env.NEXTAUTH_SECRET,
  });

  if (!token) {
    // Check for Basic Auth fallback (for API access)
    const authHeader = request.headers.get('authorization');
    if (authHeader?.startsWith('Basic ')) {
      try {
        const base64 = authHeader.split(' ')[1];
        const decoded = Buffer.from(base64, 'base64').toString('utf-8');
        const colonIndex = decoded.indexOf(':');
        
        if (colonIndex > 0) {
          const username = decoded.substring(0, colonIndex);
          const password = decoded.substring(colonIndex + 1);
          
          if (await validateBasicAuth(username, password)) {
            return {
              userId: 'basic-auth',
              email: process.env.API_AUTH_EMAIL || 'api@ghostfoundry.ai',
              roles: ['super_admin'],
              permissions: ['system:admin:all'],
            };
          }
        }
      } catch (e) {
        // Invalid Basic Auth format - silently reject
      }
    }

    return NextResponse.json(
      { success: false, error: 'Authentication required' },
      { status: 401 }
    );
  }

  const userPermissions = (token.permissions as string[]) || [];
  
  if (!hasPermission(userPermissions, check)) {
    return NextResponse.json(
      { success: false, error: 'Insufficient permissions' },
      { status: 403 }
    );
  }

  return {
    userId: token.id as string,
    email: token.email as string,
    roles: (token.roles as string[]) || [],
    permissions: userPermissions,
    department: token.department as string | undefined,
  };
}

/**
 * Check if result is an error response
 */
export function isErrorResponse(result: ApiContext | NextResponse): result is NextResponse {
  return result instanceof NextResponse;
}

/**
 * Simple authentication check without permission verification
 */
export async function requireAuth(
  request: NextRequest
): Promise<ApiContext | NextResponse> {
  // Check for ${VOCAB.controlPanel} cookie first (set by middleware for admin access)
  const gcCookie = request.cookies.get('gc_auth_token')?.value;
  if (gcCookie && validateGhostControlToken(gcCookie)) {
    return {
      userId: 'ghost-control',
      email: 'admin@ghostfoundry.ai',
      roles: ['super_admin'],
      permissions: ['system:admin:all'],
    };
  }

  const token = await getToken({
    req: request,
    secret: process.env.NEXTAUTH_SECRET,
  });

  if (!token) {
    const authHeader = request.headers.get('authorization');
    if (authHeader?.startsWith('Basic ')) {
      try {
        const base64 = authHeader.split(' ')[1];
        const decoded = Buffer.from(base64, 'base64').toString('utf-8');
        const colonIndex = decoded.indexOf(':');
        
        if (colonIndex > 0) {
          const username = decoded.substring(0, colonIndex);
          const password = decoded.substring(colonIndex + 1);
          
          if (await validateBasicAuth(username, password)) {
            return {
              userId: 'basic-auth',
              email: process.env.API_AUTH_EMAIL || 'api@ghostfoundry.ai',
              roles: ['super_admin'],
              permissions: ['system:admin:all'],
            };
          }
        }
      } catch (e) {
        // Invalid Basic Auth format - silently reject
      }
    }

    return NextResponse.json(
      { success: false, error: 'Authentication required' },
      { status: 401 }
    );
  }

  return {
    userId: token.id as string,
    email: token.email as string,
    roles: (token.roles as string[]) || [],
    permissions: (token.permissions as string[]) || [],
    department: token.department as string | undefined,
  };
}
