import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getToken } from 'next-auth/jwt';
import { BRAND, VOCAB } from '@/lib/white-label/constants';

// Routes that require authentication (page-level)
const PROTECTED_PATHS = ['/ghost-control', '/dark-factory/app'];

// Public The Hearth routes (standalone landing, login, signup, docs, pricing)
const DF_PUBLIC_PATHS = [
  '/dark-factory',
  '/dark-factory/login',
  '/dark-factory/signup',
  '/dark-factory/docs',
  '/dark-factory/pricing',
  '/dark-factory/forgot-password',
  '/dark-factory/academy',
];

// Public routes that don't require auth (even if they're under protected paths)
const PUBLIC_PATHS = ['/login', '/api/auth', '/api/dark-factory/auth'];

// Public API routes that don't require authentication
const PUBLIC_API_PATHS = [
  '/api/auth',
  '/api/dark-factory/auth',
  '/api/dark-factory/academy',
  '/api/newsletter',
  '/api/design-partner',
  '/api/contact',
  '/api/health',
  '/api/webhook',
  '/api/cron',
  '/api/tesa',
  '/api/e2e-tests',
  '/api/demos',
  '/api/heygen-video',
];

// Basic Auth credentials loaded from environment variables
function getValidCredentials() {
  const creds: { username: string; password: string }[] = [];
  const adminUser = process.env.BASIC_AUTH_ADMIN_USER;
  const adminPass = process.env.BASIC_AUTH_ADMIN_PASS;
  if (adminUser && adminPass) {
    creds.push({ username: adminUser, password: adminPass });
  }
  const guestUser = process.env.BASIC_AUTH_GUEST_USER;
  const guestPass = process.env.BASIC_AUTH_GUEST_PASS;
  if (guestUser && guestPass) {
    creds.push({ username: guestUser, password: guestPass });
  }
  return creds;
}

function isProtectedPath(pathname: string): boolean {
  return PROTECTED_PATHS.some(path => pathname.startsWith(path));
}

function isPublicPath(pathname: string): boolean {
  return PUBLIC_PATHS.some(path => pathname.startsWith(path));
}

function isDFPublicPath(pathname: string): boolean {
  // Exact match for /dark-factory (landing page)
  if (pathname === '/dark-factory') return true;
  // Check other DF public paths
  return DF_PUBLIC_PATHS.some(path => path !== '/dark-factory' && pathname.startsWith(path));
}

function validateBasicAuth(authHeader: string | null): boolean {
  if (!authHeader || !authHeader.startsWith('Basic ')) {
    return false;
  }

  try {
    const base64Credentials = authHeader.split(' ')[1];
    const credentials = atob(base64Credentials);
    const [username, password] = credentials.split(':');
    const validCreds = getValidCredentials();
    return validCreds.some(
      cred => cred.username === username && cred.password === password
    );
  } catch (e) {
    return false;
  }
}

function isPublicApiPath(pathname: string): boolean {
  return PUBLIC_API_PATHS.some(path => pathname.startsWith(path));
}

// CORS helper: add CORS headers to a response
function addCorsHeaders(response: NextResponse, request: NextRequest): NextResponse {
  const origin = request.headers.get('origin') || '';
  const allowedOrigins = [
    'https://spookysoftwaresyndicate.com',
    'https://www.spookysoftwaresyndicate.com',
    process.env.NEXTAUTH_URL || '',
  ].filter(Boolean);

  if (allowedOrigins.includes(origin) || !origin) {
    response.headers.set('Access-Control-Allow-Origin', origin || allowedOrigins[0]);
  }
  response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
  response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  response.headers.set('Access-Control-Max-Age', '86400');
  return response;
}

// In-memory rate limiter for public endpoints
const rateLimitMap = new Map<string, { count: number; resetTime: number }>();
const RATE_LIMIT_WINDOW = 60_000; // 1 minute
const RATE_LIMIT_MAX = 30; // 30 requests per minute per IP

function isRateLimited(ip: string): boolean {
  const now = Date.now();
  const entry = rateLimitMap.get(ip);
  if (!entry || now > entry.resetTime) {
    rateLimitMap.set(ip, { count: 1, resetTime: now + RATE_LIMIT_WINDOW });
    return false;
  }
  entry.count++;
  if (entry.count > RATE_LIMIT_MAX) {
    return true;
  }
  return false;
}

// Periodic cleanup of rate limit map (prevent memory leak)
function cleanupRateLimitMap() {
  const now = Date.now();
  for (const [key, entry] of rateLimitMap.entries()) {
    if (now > entry.resetTime) {
      rateLimitMap.delete(key);
    }
  }
}

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  const hostname = request.headers.get('host') || '';

  // Handle CORS preflight requests
  if (request.method === 'OPTIONS') {
    const response = new NextResponse(null, { status: 204 });
    return addCorsHeaders(response, request);
  }

  // Subdomain routing: srm.domain -> /srm
  if (hostname.startsWith('srm.')) {
    if (pathname.startsWith('/srm')) {
      return NextResponse.next();
    }
    const url = request.nextUrl.clone();
    url.pathname = pathname === '/' ? '/srm' : `/srm${pathname}`;
    return NextResponse.rewrite(url);
  }

  // Allow public page paths
  if (isPublicPath(pathname)) {
    return NextResponse.next();
  }

  // Allow The Hearth public paths (landing, login, signup, docs, pricing)
  if (isDFPublicPath(pathname)) {
    return NextResponse.next();
  }

  // --- API Route Protection ---
  if (pathname.startsWith('/api/')) {
    // Allow explicitly public API routes
    if (isPublicApiPath(pathname)) {
      // Rate limit public API endpoints
      const ip = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 
                 request.headers.get('x-real-ip') || 
                 'unknown';
      if (isRateLimited(ip)) {
        // Cleanup old entries periodically
        if (Math.random() < 0.1) cleanupRateLimitMap();
        const response = NextResponse.json(
          { error: 'Too many requests. Please try again later.' },
          { status: 429 }
        );
        response.headers.set('Retry-After', '60');
        return addCorsHeaders(response, request);
      }
      if (Math.random() < 0.1) cleanupRateLimitMap();
      const response = NextResponse.next();
      return addCorsHeaders(response, request);
    }

    // Non-public API routes require authentication
    const token = await getToken({
      req: request,
      secret: process.env.NEXTAUTH_SECRET,
    });

    // Check session token
    if (token) {
      const response = NextResponse.next();
      return addCorsHeaders(response, request);
    }

    // Check ghost-control auth cookie
    const gcAuthCookie = request.cookies.get('gc_auth_token')?.value;
    if (gcAuthCookie === 'syndicate_authenticated') {
      const response = NextResponse.next();
      return addCorsHeaders(response, request);
    }

    // Check Basic Auth
    const authHeader = request.headers.get('authorization');
    if (validateBasicAuth(authHeader)) {
      const response = NextResponse.next();
      return addCorsHeaders(response, request);
    }

    // Unauthenticated API request
    const response = new NextResponse(
      JSON.stringify({ error: 'Authentication required' }),
      {
        status: 401,
        headers: { 'Content-Type': 'application/json' },
      }
    );
    return addCorsHeaders(response, request);
  }

  // --- Page-level Protection ---
  // Non-protected pages pass through
  if (!isProtectedPath(pathname)) {
    return NextResponse.next();
  }

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

  // Check for ghost-control auth cookie
  const gcAuthCookie = request.cookies.get('gc_auth_token')?.value;

  // Helper: set gc_auth_token cookie on response for Ghost Control pages
  const isGhostControl = pathname.startsWith('/ghost-control');
  function ensureGcCookie(response: NextResponse) {
    if (isGhostControl && gcAuthCookie !== 'syndicate_authenticated') {
      response.cookies.set('gc_auth_token', 'syndicate_authenticated', {
        httpOnly: false,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        path: '/',
        maxAge: 24 * 60 * 60,
      });
    }
    return response;
  }

  if (token) {
    return ensureGcCookie(NextResponse.next());
  }

  if (gcAuthCookie === 'syndicate_authenticated') {
    return NextResponse.next();
  }

  // Check for Basic Auth (API access fallback)
  const authHeader = request.headers.get('authorization');
  if (validateBasicAuth(authHeader)) {
    return ensureGcCookie(NextResponse.next());
  }

  // Not authenticated - redirect to login for browser requests
  const acceptHeader = request.headers.get('accept') || '';
  if (acceptHeader.includes('text/html')) {
    const loginPath = pathname.startsWith('/dark-factory') ? '/dark-factory/login' : '/login';
    const loginUrl = new URL(loginPath, request.url);
    loginUrl.searchParams.set('callbackUrl', pathname);
    return NextResponse.redirect(loginUrl);
  }

  // Return 401 for non-browser requests
  return new NextResponse('Authentication required', {
    status: 401,
    headers: {
      'WWW-Authenticate': `Basic realm="${BRAND.companyName}"`,
    },
  });
}

export const config = {
  matcher: [
    '/ghost-control/:path*',
    '/dark-factory/:path*',
    '/login',
    '/dark-factory/app/:path*',
    '/srm/:path*',
    '/api/:path*',
    '/((?!_next|favicon|images|.*\\.).*)',
  ],
};
