import { NextRequest, NextResponse } from 'next/server';
import { db } from '@/lib/db';

/**
 * Admin session verification utility.
 * 
 * The admin auth system uses a simple token-based approach:
 * - On login, the admin receives a session token (base64 of admin ID + timestamp)
 * - The token is sent via the `x-admin-token` header on subsequent requests
 * - This middleware verifies the token and checks the admin still exists and is active
 * 
 * IMPORTANT: This is a basic auth system for a demo/prototype app.
 * For production, use proper session management (NextAuth.js, JWT with secrets, etc.)
 */

interface AdminSession {
  id: string;
  role: string;
  source: 'user' | 'team' | 'hardcoded';
}

// Simple encode/decode for admin sessions (NOT encryption - for demo purposes)
function encodeSession(admin: AdminSession): string {
  const payload = JSON.stringify({ ...admin, ts: Date.now() });
  return Buffer.from(payload).toString('base64');
}

function decodeSession(token: string): (AdminSession & { ts: number }) | null {
  try {
    const payload = Buffer.from(token, 'base64').toString('utf-8');
    const parsed = JSON.parse(payload);
    if (!parsed.id || !parsed.role || !parsed.source) return null;
    // Token expires after 24 hours
    if (Date.now() - parsed.ts > 24 * 60 * 60 * 1000) return null;
    return parsed;
  } catch {
    return null;
  }
}

/**
 * Generate a session token for an authenticated admin.
 */
export function generateAdminToken(admin: { id: string; role: string; source: 'user' | 'team' | 'hardcoded' }): string {
  return encodeSession(admin);
}

/**
 * Verify an admin request by checking the x-admin-token header.
 * Returns the session data if valid, or an error response if invalid.
 */
export async function verifyAdminAuth(request: NextRequest): Promise<{ session: AdminSession } | { error: NextResponse }> {
  const token = request.headers.get('x-admin-token');

  if (!token) {
    return {
      error: NextResponse.json(
        { success: false, error: 'Authentication required. Please log in as admin.' },
        { status: 401 }
      ),
    };
  }

  const session = decodeSession(token);

  if (!session) {
    return {
      error: NextResponse.json(
        { success: false, error: 'Invalid or expired admin session. Please log in again.' },
        { status: 401 }
      ),
    };
  }

  // Hardcoded super admin tokens are always valid (initial setup fallback)
  if (session.source === 'hardcoded') {
    // These are known super admins - no DB check needed
    return { session };
  }

  // Verify the admin still exists and is active
  if (session.source === 'team') {
    const teamMember = await db.teamMember.findUnique({
      where: { id: session.id },
      select: { id: true, isActive: true, role: true },
    });

    if (!teamMember || !teamMember.isActive) {
      return {
        error: NextResponse.json(
          { success: false, error: 'Admin account not found or deactivated.' },
          { status: 403 }
        ),
      };
    }
  } else {
    const user = await db.user.findUnique({
      where: { id: session.id },
      select: { id: true, isActive: true, roles: true },
    });

    if (!user || !user.isActive) {
      return {
        error: NextResponse.json(
          { success: false, error: 'Admin account not found or deactivated.' },
          { status: 403 }
        ),
      };
    }

    if (!['admin', 'super_admin', 'houseOwner', 'shopOwner'].includes(user.roles)) {
      return {
        error: NextResponse.json(
          { success: false, error: 'Insufficient permissions.' },
          { status: 403 }
        ),
      };
    }
  }

  return { session };
}

/**
 * Verify admin auth and check a specific permission.
 */
export async function verifyAdminPermission(
  request: NextRequest,
  permission: string
): Promise<{ session: AdminSession } | { error: NextResponse }> {
  const authResult = await verifyAdminAuth(request);

  if ('error' in authResult) return authResult;

  const { session } = authResult;

  // Hardcoded super admins have all permissions
  if (session.source === 'hardcoded') {
    return { session };
  }

  // Super admins (from User table with role 'admin' or 'super_admin') have all permissions
  if (session.source === 'user' && ['super_admin', 'admin'].includes(session.role)) {
    return { session };
  }

  // Team members need specific permission checks
  if (session.source === 'team') {
    const teamMember = await db.teamMember.findUnique({
      where: { id: session.id },
      select: { [permission]: true, role: true },
    });

    if (!teamMember) {
      return {
        error: NextResponse.json(
          { success: false, error: 'Admin account not found.' },
          { status: 403 }
        ),
      };
    }

    // Super admin team members have all permissions
    if (teamMember.role === 'super_admin') {
      return { session };
    }

    if (!(teamMember as Record<string, unknown>)[permission]) {
      return {
        error: NextResponse.json(
          { success: false, error: `You do not have permission: ${permission}` },
          { status: 403 }
        ),
      };
    }
  }

  return { session };
}

/**
 * Check if the session belongs to a super admin.
 */
export function isSuperAdminSession(session: AdminSession): boolean {
  return session.role === 'super_admin';
}

// ============ USER SESSION TOKENS ============

interface UserSession {
  id: string;
  email: string;
  ts: number;
}

/**
 * Generate a session token for an authenticated user.
 * Uses the same base64 encoding as admin tokens for consistency.
 */
export function generateUserToken(user: { id: string; email: string }): string {
  const payload = JSON.stringify({ id: user.id, email: user.email, ts: Date.now() });
  return Buffer.from(payload).toString('base64');
}

/**
 * Verify a user request by checking the x-user-token header.
 * Returns the user session data if valid, or an error response if invalid.
 * Also verifies the user still exists and is active in the database.
 */
export async function verifyUserAuth(request: NextRequest): Promise<{ session: UserSession } | { error: NextResponse }> {
  const token = request.headers.get('x-user-token');

  if (!token) {
    return {
      error: NextResponse.json(
        { success: false, error: 'Authentication required. Please log in.' },
        { status: 401 }
      ),
    };
  }

  try {
    const payload = Buffer.from(token, 'base64').toString('utf-8');
    const session = JSON.parse(payload) as UserSession;

    if (!session.id || !session.email) {
      return {
        error: NextResponse.json(
          { success: false, error: 'Invalid user session. Please log in again.' },
          { status: 401 }
        ),
      };
    }

    // Token expires after 24 hours
    if (Date.now() - session.ts > 24 * 60 * 60 * 1000) {
      return {
        error: NextResponse.json(
          { success: false, error: 'Session expired. Please log in again.' },
          { status: 401 }
        ),
      };
    }

    // Verify user still exists and is active
    const user = await db.user.findUnique({
      where: { id: session.id },
      select: { id: true, isActive: true },
    });

    if (!user || !user.isActive) {
      return {
        error: NextResponse.json(
          { success: false, error: 'User account not found or deactivated.' },
          { status: 403 }
        ),
      };
    }

    return { session };
  } catch {
    return {
      error: NextResponse.json(
        { success: false, error: 'Invalid user session. Please log in again.' },
        { status: 401 }
      ),
    };
  }
}
