import { Request, Response, NextFunction } from 'express';
import { supabaseAdmin } from '../config/supabase';
import { db } from '../database/connection';
import { users } from '../database/schema';
import { eq } from 'drizzle-orm';

export interface AuthenticatedRequest extends Request {
  user?: {
    id: string;
    email: string;
    role: string;
  };
}

declare global {
  namespace Express {
    interface Request {
      user?: {
        id: string;
        email: string;
        role: string;
      };
    }
  }
}

// JWT is valid → req.user filled. Role is read from public.users (not the token) so DB role changes apply immediately.
export const authenticateUser = async (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
) => {
  try {
    const authHeader = req.headers.authorization;
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({ error: 'No token provided' });
    }

    const token = authHeader.split(' ')[1];
    
    // Verify the JWT token with Supabase
    const { data: { user }, error } = await supabaseAdmin.auth.getUser(token);

    if (error || !user) {
      return res.status(401).json({ error: 'Invalid token' });
    }

    // Get role from database users table
    let role = 'user';
    try {
      const [dbUser] = await db
        .select({ role: users.role })
        .from(users)
        .where(eq(users.id, user.id))
        .limit(1);
      
      if (dbUser) {
        role = dbUser.role;
      }
    } catch (dbError) {
      console.error('Error fetching user role from database:', dbError);
      // Fall back to user_metadata if database query fails
      role = user.user_metadata?.role || 'user';
    }

    // Add user info to request
    req.user = {
      id: user.id,
      email: user.email!,
      role
    };

    return next();
  } catch (error) {
    console.error('Authentication error:', error);
    return res.status(401).json({ error: 'Authentication failed' });
  }
};

export const requireAdmin = (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
) => {
  if (!req.user || req.user.role !== 'admin') {
    return res.status(403).json({ error: 'Admin access required' });
  }
  return next();
};

export const requireUserOrAdmin = (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
) => {
  if (!req.user || (req.user.role !== 'user' && req.user.role !== 'admin')) {
    return res.status(403).json({ error: 'User or admin access required' });
  }
  return next();
};

export const requireAdminOrTeam = (
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
) => {
  if (!req.user || (req.user.role !== 'admin' && req.user.role !== 'volunteer')) {
    return res.status(403).json({ error: 'Admin or team member access required' });
  }
  return next();
};
