import { jwtVerify } from 'jose';
import type { FastifyRequest } from 'fastify';
import { config, productId } from './config.js';

export interface AuthenticatedRequest extends FastifyRequest {
  authUserId?: string;
  authRole?: string;
  authEmail?: string;
  authProductId?: string;
}

export async function extractAuth(req: FastifyRequest): Promise<{ userId: string; role: string; email?: string; productId?: string } | null> {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return null;
  }

  const token = authHeader.slice(7);
  try {
    const { payload } = await jwtVerify(
      token,
      new TextEncoder().encode(config.JWT_SECRET),
      { issuer: 'bytelyst-platform' }
    );

    // Check if user has admin role for the devops product
    // If they have global admin role, they can access
    // Otherwise, check their per-product membership
    const globalRole = (payload.role as string) || 'user';
    const currentProductId = payload.productId as string;
    const targetProductId = productId; // This dashboard's product ID

    let effectiveRole = globalRole;

    // If not global admin, check per-product membership
    if (globalRole !== 'admin' && payload.products) {
      const products = payload.products as Array<{ productId: string; role: string; plan: string }>;
      const devopsMembership = products.find(p => p.productId === targetProductId);
      if (devopsMembership && devopsMembership.role === 'admin') {
        effectiveRole = 'admin';
      }
    }

    return {
      userId: payload.sub as string,
      role: effectiveRole,
      email: payload.email as string,
      productId: currentProductId,
    };
  } catch {
    return null;
  }
}

export class AuthError extends Error {
  constructor(message: string, public statusCode: number = 401) {
    super(message);
    this.name = 'AuthError';
  }
}

export class BadRequestError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'BadRequestError';
  }
}

export function requireAdmin(req: FastifyRequest): { userId: string } {
  const authReq = req as AuthenticatedRequest;
  if (!authReq.authUserId || authReq.authRole !== 'admin') {
    throw new AuthError('Admin access required', 403);
  }
  return { userId: authReq.authUserId };
}
