import React, { useState, useCallback, useMemo, lazy, Suspense, useEffect } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Link } from "wouter";
import { useAuth } from "@/hooks/useAuth";
import { Plus, Phone, Mail, MapPin, Calendar, LayoutGrid, Move, Trash2, Edit, RefreshCw, GraduationCap, KeyRound, Copy, Send } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import type { NewHire, Trainer } from "@shared/schema";

import { graduationSmsStatusMessage } from "@/lib/graduation-sms-status";

// The graduation columns are added by the backend independently of the shared
// schema migration. Keep them optional here so this page remains compatible
// while older API responses are still in use.
type PrimeRep = NewHire & {
  graduatedAt?: string | null;
  graduatedBy?: string | null;
  graduatedSalesRepId?: string | null;
};

type PrimeRepLoginAccess = {
  repId: string;
  name: string;
  email: string;
  signupPath: string;
  signInPath: string;
  instructions: string;
  invitationAvailable: boolean;
};

// Lazy load modals and heavy components
const AddNewHireModal = lazy(() => import("@/components/modals/add-new-hire-modal"));
const EditNewHireModal = lazy(() => import("@/components/modals/edit-new-hire-modal"));
const AssignTrainerModal = lazy(() => import("@/components/modals/assign-trainer-modal"));
const TrainerAssignmentBoard = lazy(() => import("@/components/drag-drop/trainer-assignment-board"));

// Memoized Prime Rep card component
const NewHireCard = React.memo(({ 
  hire, 
  trainers,
  onEdit, 
  onDelete, 
  onAssignTrainer,
  onGraduate,
  onLoginAccess,
  isDeleting,
  isGraduating,
  canGraduate,
  canLoginAccess,
}: { 
  hire: PrimeRep;
  trainers: Trainer[];
  onEdit: (hire: PrimeRep) => void;
  onDelete: (hireId: string) => void;
  onAssignTrainer: (hire: PrimeRep) => void;
  onGraduate: (hire: PrimeRep) => Promise<boolean>;
  onLoginAccess: (hire: PrimeRep) => void;
  isDeleting: boolean;
  isGraduating: boolean;
  canGraduate: boolean;
  canLoginAccess: boolean;
}) => {
  const isGraduated = Boolean(hire.graduatedAt);
  const [graduateDialogOpen, setGraduateDialogOpen] = useState(false);

  const getTrainerName = useCallback((trainerId: string | null) => {
    if (!trainerId) return "Unassigned";
    const trainer = trainers.find(t => t.id === trainerId);
    return trainer ? trainer.name : "Unknown Trainer";
  }, [trainers]);

  return (
    <Card className="hover:shadow-lg transition-shadow" data-testid={`new-hire-card-${hire.id}`}>
      <CardHeader className="pb-4">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <div className="flex min-w-0 flex-wrap items-center gap-3">
            <CardTitle className="text-lg break-words">{hire.name}</CardTitle>
            {isGraduated ? (
              <Badge className="bg-emerald-100 text-emerald-700">Graduated</Badge>
            ) : (
              <Badge 
                variant={hire.trainerId ? "default" : "secondary"}
                className={hire.trainerId ? "bg-blue-100 text-blue-700" : "bg-orange-100 text-orange-700"}
              >
                {hire.trainerId ? "Assigned" : "Unassigned"}
              </Badge>
            )}
          </div>
          {!isGraduated && (
            <div className="flex flex-wrap items-center gap-1">
              <Button
                variant="ghost"
                size="sm"
                className="text-blue-600 hover:text-blue-700 hover:bg-blue-50"
                data-testid={`edit-new-hire-${hire.id}`}
                onClick={() => onEdit(hire)}
              >
                <Edit className="w-4 h-4" />
              </Button>
              <AlertDialog>
                <AlertDialogTrigger asChild>
                  <Button
                    variant="ghost"
                    size="sm"
                    className="text-red-600 hover:text-red-700 hover:bg-red-50"
                    data-testid={`delete-new-hire-${hire.id}`}
                    disabled={isDeleting}
                  >
                    <Trash2 className="w-4 h-4" />
                  </Button>
                </AlertDialogTrigger>
                <AlertDialogContent>
                  <AlertDialogHeader>
                    <AlertDialogTitle>Delete New Hire</AlertDialogTitle>
                    <AlertDialogDescription>
                      Are you sure you want to delete <strong>{hire.name}</strong>? This action cannot be undone and will remove all associated training data.
                    </AlertDialogDescription>
                  </AlertDialogHeader>
                  <AlertDialogFooter>
                    <AlertDialogCancel>Cancel</AlertDialogCancel>
                    <AlertDialogAction
                      onClick={() => onDelete(hire.id)}
                      disabled={isDeleting}
                      className="bg-red-600 hover:bg-red-700"
                    >
                      {isDeleting ? "Deleting..." : "Delete"}
                    </AlertDialogAction>
                  </AlertDialogFooter>
                </AlertDialogContent>
              </AlertDialog>
              {canGraduate && (
                <AlertDialog open={graduateDialogOpen} onOpenChange={setGraduateDialogOpen}>
                  <AlertDialogTrigger asChild>
                    <Button
                      variant="ghost"
                      size="sm"
                      className="text-emerald-700 hover:bg-emerald-50 hover:text-emerald-800"
                      data-testid={`graduate-new-hire-${hire.id}`}
                      disabled={isGraduating}
                      aria-label={`Graduate ${hire.name} to Sales Rep`}
                    >
                      <GraduationCap className="w-4 h-4" />
                      <span>Graduate to Sales Rep</span>
                    </Button>
                  </AlertDialogTrigger>
                  <AlertDialogContent>
                    <AlertDialogHeader>
                      <AlertDialogTitle>Graduate to Sales Rep?</AlertDialogTitle>
                      <AlertDialogDescription asChild>
                        <div className="space-y-2">
                          <p><strong>{hire.name}</strong> will move to the Sales roster.</p>
                          <p>This preserves their training history, contact details, and SMS preferences. Nothing is deleted, and no password is sent.</p>
                          <p>Their individual login will continue working after graduation. No one is graduated automatically.</p>
                          <p>A congratulations text welcoming them to Phase 2 will be queued on the live app if they have a phone number and current SMS consent. Preview graduations do not send texts.</p>
                          <blockquote className="rounded-md bg-muted p-3 text-sm">
                            Congratulations, {hire.name.trim().split(/\s+/)[0]}! Welcome to Phase 2! We're so proud of the hard work, growth, and commitment you've shown during training. You've earned this next step, and we're excited to keep supporting you as you grow. - Your team
                            <br />Reply STOP to opt out.
                          </blockquote>
                        </div>
                      </AlertDialogDescription>
                    </AlertDialogHeader>
                    <AlertDialogFooter>
                      <AlertDialogCancel disabled={isGraduating}>Cancel</AlertDialogCancel>
                      <AlertDialogAction
                        data-testid={`confirm-graduate-new-hire-${hire.id}`}
                        disabled={isGraduating}
                        onClick={async (event) => {
                          event.preventDefault();
                          const graduated = await onGraduate(hire);
                          if (graduated) setGraduateDialogOpen(false);
                        }}
                      >
                        {isGraduating ? "Graduating…" : "Graduate to Sales Rep"}
                      </AlertDialogAction>
                    </AlertDialogFooter>
                  </AlertDialogContent>
                </AlertDialog>
              )}
              {canLoginAccess && (
                <Button
                  variant="ghost"
                  size="sm"
                  className="text-violet-700 hover:bg-violet-50 hover:text-violet-800"
                  data-testid={`login-access-${hire.id}`}
                  onClick={() => onLoginAccess(hire)}
                  aria-label={`Login access for ${hire.name}`}
                >
                  <KeyRound className="w-4 h-4" />
                  <span>Login access</span>
                </Button>
              )}
            </div>
          )}
        </div>
      </CardHeader>
      <CardContent className="space-y-3">
        {isGraduated && (
          <div className="rounded-md border border-emerald-200 bg-emerald-50 p-3 text-sm text-emerald-900">
            <p>
              Graduated{hire.graduatedAt ? ` on ${new Date(hire.graduatedAt).toLocaleDateString()}` : ""}
            </p>
            <Button asChild variant="link" size="sm" className="h-auto px-0 text-emerald-800">
              <Link href="/sales-reps">View Sales Reps</Link>
            </Button>
          </div>
        )}
        <div className="flex items-center space-x-2 text-sm">
          <Calendar className="w-4 h-4 text-muted-foreground" />
          <span className="text-muted-foreground">Start Date:</span>
          <span>{hire.startDate}</span>
        </div>
        
        <div className="flex items-center space-x-2 text-sm">
          <MapPin className="w-4 h-4 text-muted-foreground" />
          <span className="text-muted-foreground">Territory:</span>
          <span>{hire.territory}</span>
        </div>
        
        <div className="flex items-center space-x-2 text-sm">
          <Phone className="w-4 h-4 text-muted-foreground" />
          <span>{hire.phone}</span>
        </div>
        
        <div className="flex items-center space-x-2 text-sm">
          <Mail className="w-4 h-4 text-muted-foreground" />
          <span>{hire.email}</span>
        </div>
        
        <div className="pt-2 border-t border-border">
          <div className="flex items-center space-x-2 text-sm">
            <span className="text-muted-foreground">Trainer:</span>
            <span className={hire.trainerId ? "text-foreground" : "text-orange-600"}>
              {getTrainerName(hire.trainerId)}
            </span>
          </div>
        </div>
        
        {!isGraduated && !hire.trainerId && (
          <Button
            data-testid={`assign-trainer-${hire.id}`}
            size="sm"
            className="w-full mt-3"
            onClick={() => onAssignTrainer(hire)}
          >
            Assign Trainer
          </Button>
        )}
      </CardContent>
    </Card>
  );
});

NewHireCard.displayName = "NewHireCard";

// Loading skeleton component
const NewHireCardSkeleton = () => (
  <Card className="animate-pulse">
    <CardHeader className="pb-4">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <div className="h-6 bg-gray-200 rounded w-32"></div>
          <div className="h-5 bg-gray-200 rounded w-20"></div>
        </div>
      </div>
    </CardHeader>
    <CardContent className="space-y-3">
      <div className="h-4 bg-gray-200 rounded w-full"></div>
      <div className="h-4 bg-gray-200 rounded w-3/4"></div>
      <div className="h-4 bg-gray-200 rounded w-2/3"></div>
      <div className="h-4 bg-gray-200 rounded w-1/2"></div>
    </CardContent>
  </Card>
);

export default function NewHires() {
  const { user } = useAuth();
  const canGraduate = user?.role === "manager" || user?.role === "admin";
  const canLoginAccess = canGraduate;
  const [showAddNewHire, setShowAddNewHire] = useState(false);
  const [showEditNewHire, setShowEditNewHire] = useState(false);
  const [showAssignTrainer, setShowAssignTrainer] = useState(false);
  const [selectedNewHire, setSelectedNewHire] = useState<PrimeRep | null>(null);
  const [editingNewHire, setEditingNewHire] = useState<PrimeRep | null>(null);
  const [activeTab, setActiveTab] = useState("cards");
  const [showGraduated, setShowGraduated] = useState(false);
  const [newHires, setNewHires] = useState<PrimeRep[]>([]);
  const [trainers, setTrainers] = useState<Trainer[]>([]);
  const [loginAccessRep, setLoginAccessRep] = useState<PrimeRep | null>(null);
  const [loginAccess, setLoginAccess] = useState<PrimeRepLoginAccess | null>(null);
  const [loginAccessError, setLoginAccessError] = useState<string | null>(null);
  const [showLoginAccess, setShowLoginAccess] = useState(false);
  const [isLoadingLoginAccess, setIsLoadingLoginAccess] = useState(false);
  const [isSendingInvitation, setIsSendingInvitation] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [hasError, setHasError] = useState<string | null>(null);
  const { toast } = useToast();
  const queryClient = useQueryClient();

  // Simple, direct data fetching
  const fetchData = useCallback(async (includeGraduated = showGraduated) => {
    try {
      setIsLoading(true);
      setHasError(null);
      console.log("🔍 Fetching Prime Reps and trainers directly...");
      
      // Fetch both endpoints
      const [hiresResponse, trainersResponse] = await Promise.all([
        apiRequest('GET', includeGraduated ? '/api/new-hires?includeGraduated=true' : '/api/new-hires'),
        apiRequest('GET', '/api/trainers')
      ]);
      
      console.log("📡 Direct fetch responses:", hiresResponse.status, trainersResponse.status);
      
      if (!hiresResponse.ok || !trainersResponse.ok) {
        throw new Error(`HTTP error - hires: ${hiresResponse.status}, trainers: ${trainersResponse.status}`);
      }
      
      const [hiresData, trainersData] = await Promise.all([
        hiresResponse.json(),
        trainersResponse.json()
      ]);
      
      console.log("✅ New hires data received:", hiresData);
      console.log("✅ Trainers data received:", trainersData);
      
      setNewHires(Array.isArray(hiresData) ? hiresData : []);
      setTrainers(Array.isArray(trainersData) ? trainersData : []);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to fetch data';
      console.error("❌ Fetch failed:", errorMessage);
      setHasError(errorMessage);
      setNewHires([]);
      setTrainers([]);
    } finally {
      setIsLoading(false);
    }
  }, [showGraduated]);

  // Fetch data on component mount
  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const deleteNewHire = useMutation({
    mutationFn: (newHireId: string) => apiRequest("DELETE", `/api/new-hires/${newHireId}`),
    onSuccess: () => {
      fetchData(); // Refresh data after deletion
      toast({
        title: "Success",
        description: "New hire deleted successfully",
      });
    },
    onError: () => {
      toast({
        title: "Error",
        description: "Failed to delete Prime Rep",
        variant: "destructive",
      });
    },
  });

  const invalidateGraduationQueries = useCallback(() => {
    // Invalidate every list that can contain a Prime Rep or Sales Rep. Prefix
    // matching also covers team-specific and includeGraduated query variants.
    [
      "/api/new-hires",
      "/api/sales-reps",
      "/api/identity-prime-reps",
      "/api/identity-sales-reps",
      "/api/claude-trainings/reps",
      "/api/training-pairs",
    ].forEach((queryKey) => {
      void queryClient.invalidateQueries({ queryKey: [queryKey] });
    });
  }, [queryClient]);

  const graduateNewHire = useMutation({
    mutationFn: async (hire: PrimeRep) => {
      const response = await apiRequest("POST", `/api/new-hires/${hire.id}/graduate`);
      return (await response.json()) as {
        newHire?: PrimeRep;
        salesRep?: { id: string; name?: string };
        alreadyGraduated?: boolean;
        graduationSms?: { status: string; reason?: string | null };
      };
    },
    onSuccess: (result, hire) => {
      invalidateGraduationQueries();
      // The server has confirmed the transition. Reflect it locally rather
      // than waiting for a full page reload; the subsequent fetch reconciles
      // the complete response and handles concurrent changes.
      if (result.newHire) {
        setNewHires((current) =>
          showGraduated
            ? current.map((item) => item.id === hire.id ? result.newHire! : item)
            : current.filter((item) => item.id !== hire.id),
        );
      } else if (!showGraduated) {
        setNewHires((current) => current.filter((item) => item.id !== hire.id));
      }
      void fetchData();
      const smsMessage = graduationSmsStatusMessage(result.graduationSms);
      if (result.alreadyGraduated) {
        toast({
          title: "Prime Rep already graduated",
          description: `This Prime Rep is already on the Sales roster.${smsMessage}`,
        });
      } else {
        toast({
          title: "Prime Rep graduated",
          description: `${hire.name} was moved to the Sales roster.${smsMessage}`,
        });
      }
    },
    onError: (error) => {
      // apiRequest rejects non-2xx responses, so failed or duplicate
      // requests never receive the success toast or an optimistic list update.
      toast({
        title: "Unable to graduate Prime Rep",
        description: error instanceof Error ? error.message.replace(/^\d{3}:\s*/, "") : "Please try again.",
        variant: "destructive",
      });
    },
  });

  // Memoized callbacks to prevent unnecessary re-renders
  const handleEditNewHire = useCallback((hire: PrimeRep) => {
    setEditingNewHire(hire);
    setShowEditNewHire(true);
  }, []);

  const handleDeleteNewHire = useCallback((hireId: string) => {
    deleteNewHire.mutate(hireId);
  }, [deleteNewHire]);

  const handleAssignTrainer = useCallback((hire: PrimeRep) => {
    setSelectedNewHire(hire);
    setShowAssignTrainer(true);
  }, []);

  const handleRefresh = useCallback(() => {
    fetchData();
  }, [fetchData]);

  const handleAddNewHire = useCallback(() => {
    setShowAddNewHire(true);
  }, []);

  const handleGraduateNewHire = useCallback(async (hire: PrimeRep) => {
    try {
      await graduateNewHire.mutateAsync(hire);
      return true;
    } catch {
      return false;
    }
  }, [graduateNewHire]);

  const handleLoginAccess = useCallback(async (hire: PrimeRep) => {
    setLoginAccessRep(hire);
    setLoginAccess(null);
    setLoginAccessError(null);
    setShowLoginAccess(true);
    setIsLoadingLoginAccess(true);
    try {
      const response = await apiRequest("GET", `/api/new-hires/${hire.id}/login-access`);
      setLoginAccess((await response.json()) as PrimeRepLoginAccess);
    } catch (error) {
      setLoginAccessError(
        error instanceof Error
          ? error.message.replace(/^\d{3}:\s*/, "")
          : "Unable to prepare login access. Please try again.",
      );
    } finally {
      setIsLoadingLoginAccess(false);
    }
  }, []);

  const handleCopySignupLink = useCallback(async () => {
    if (!loginAccess) return;
    try {
      if (!navigator.clipboard?.writeText) throw new Error("Clipboard unavailable");
      await navigator.clipboard.writeText(loginAccess.signupPath);
      toast({
        title: "Sign-up link copied",
        description: "Share the link with the Prime Rep.",
      });
    } catch {
      toast({
        title: "Unable to copy link",
        description: "Copy the sign-up link directly from the dialog.",
        variant: "destructive",
      });
    }
  }, [loginAccess, toast]);

  const handleSendInvitation = useCallback(async () => {
    if (!loginAccessRep || !loginAccess) return;
    setIsSendingInvitation(true);
    try {
      const response = await apiRequest(
        "POST",
        `/api/new-hires/${loginAccessRep.id}/login-access/invite`,
      );
      const result = await response.json() as PrimeRepLoginAccess & {
        invitationSent?: boolean;
        alreadyRegistered?: boolean;
      };
      setLoginAccess(result);
      toast({
        title: result.alreadyRegistered ? "Account already registered" : "Invitation sent",
        description: result.alreadyRegistered
          ? `${loginAccess.email} can use the sign-in link.`
          : `Clerk sent a sign-up invitation to ${loginAccess.email}.`,
      });
    } catch (error) {
      toast({
        title: "Unable to send invitation",
        description: error instanceof Error
          ? error.message.replace(/^\d{3}:\s*/, "")
          : "Copy the sign-up link instead.",
        variant: "destructive",
      });
    } finally {
      setIsSendingInvitation(false);
    }
  }, [loginAccess, loginAccessRep, toast]);

  const handleCloseLoginAccess = useCallback((open: boolean) => {
    setShowLoginAccess(open);
    if (!open) {
      setLoginAccessRep(null);
      setLoginAccess(null);
      setLoginAccessError(null);
    }
  }, []);

  const handleCloseAddModal = useCallback(() => {
    setShowAddNewHire(false);
  }, []);

  const handleCloseEditModal = useCallback(() => {
    setShowEditNewHire(false);
    setEditingNewHire(null);
  }, []);

  const handleCloseAssignModal = useCallback(() => {
    setShowAssignTrainer(false);
    setSelectedNewHire(null);
  }, []);

  // Memoized Prime Rep cards to prevent unnecessary re-renders
  const newHireCards = useMemo(() => 
    newHires.map((hire) => (
      <NewHireCard
        key={hire.id}
        hire={hire}
        trainers={trainers}
        onEdit={handleEditNewHire}
        onDelete={handleDeleteNewHire}
        onAssignTrainer={handleAssignTrainer}
        onGraduate={handleGraduateNewHire}
        onLoginAccess={handleLoginAccess}
        isDeleting={deleteNewHire.isPending}
        isGraduating={graduateNewHire.isPending && graduateNewHire.variables?.id === hire.id}
        canGraduate={canGraduate}
        canLoginAccess={canLoginAccess}
      />
    )),
    [newHires, trainers, handleEditNewHire, handleDeleteNewHire, handleAssignTrainer, handleGraduateNewHire, handleLoginAccess, deleteNewHire.isPending, graduateNewHire.isPending, graduateNewHire.variables?.id, canGraduate, canLoginAccess]
  );

  // Loading state with skeleton
  if (isLoading) {
    return (
      <div className="flex-1 overflow-auto">
        <header className="bg-card border-b border-border px-6 py-4">
          <div className="flex items-center justify-between">
            <div>
              <h2 className="text-2xl font-bold text-foreground">Prime Reps</h2>
              <p className="text-muted-foreground">Track and manage Prime Rep onboarding</p>
            </div>
          </div>
        </header>
        <main className="p-6">
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            {Array.from({ length: 6 }).map((_, i) => (
              <NewHireCardSkeleton key={i} />
            ))}
          </div>
        </main>
      </div>
    );
  }

  // Error state
  if (hasError) {
    return (
      <div className="flex-1 overflow-auto">
        <div className="flex items-center justify-center min-h-[400px]">
          <div className="text-center">
            <p className="text-red-600 mb-4">Failed to load Prime Reps</p>
            <Button onClick={handleRefresh} variant="secondary" className="bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-400 dark:border-gray-500 hover:bg-gray-100 dark:hover:bg-gray-600">
              <RefreshCw className="w-4 h-4 mr-2" />
              Try Again
            </Button>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="flex-1 overflow-auto">
      <header className="bg-card border-b border-border px-6 py-4">
        <div className="flex items-center justify-between">
          <div>
            <h2 className="text-2xl font-bold text-foreground">Prime Reps</h2>
            <p className="text-muted-foreground">Track and manage Prime Rep onboarding</p>
          </div>
          <div className="flex gap-2">
            <Button
              variant="secondary"
              onClick={handleRefresh}
              className="bg-white dark:bg-gray-700 text-gray-900 dark:text-white border border-gray-400 dark:border-gray-500 hover:bg-gray-100 dark:hover:bg-gray-600"
              title="Refresh Prime Reps list"
            >
              <RefreshCw className="w-4 h-4" />
            </Button>
            <Button
              data-testid="add-prime-rep-button"
              onClick={handleAddNewHire}
            >
              <Plus className="w-4 h-4 mr-2" />
              Add Prime Rep
            </Button>
            {canGraduate && (
              <Button
                variant={showGraduated ? "default" : "outline"}
                onClick={() => setShowGraduated((current) => !current)}
                data-testid="show-graduated-prime-reps"
              >
                {showGraduated ? "Hide graduated" : "Show graduated"}
              </Button>
            )}
          </div>
        </div>
      </header>

      <main className="p-6">
        <Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
          <TabsList className="mb-6">
            <TabsTrigger value="cards" className="flex items-center gap-2">
              <LayoutGrid className="w-4 h-4" />
              Card View
            </TabsTrigger>
            <TabsTrigger value="board" className="flex items-center gap-2">
              <Move className="w-4 h-4" />
              Drag & Drop Board
            </TabsTrigger>
          </TabsList>

          <TabsContent value="cards">
            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
              {newHireCards}
            </div>

            {newHires.length === 0 && (
              <div className="text-center py-12">
                <Calendar className="w-12 h-12 text-muted-foreground mx-auto mb-4" />
                <h3 className="text-lg font-medium text-foreground mb-2">
                  {showGraduated ? "No graduated Prime Reps found" : "No Prime Reps found"}
                </h3>
                {showGraduated ? (
                  <p className="text-muted-foreground">Graduated Prime Reps will appear here.</p>
                ) : (
                  <>
                    <p className="text-muted-foreground mb-4">Start onboarding new team members</p>
                    <Button
                      data-testid="add-first-prime-rep-button"
                      onClick={handleAddNewHire}
                    >
                      <Plus className="w-4 h-4 mr-2" />
                      Add Prime Rep
                    </Button>
                  </>
                )}
              </div>
            )}
          </TabsContent>

          <TabsContent value="board">
            <Suspense fallback={
              <div className="flex items-center justify-center h-96">
                <div className="text-center">
                  <div className="h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent mx-auto mb-4" />
                  <p className="text-muted-foreground">Loading board...</p>
                </div>
              </div>
            }>
              <TrainerAssignmentBoard
                trainers={trainers}
                newHires={newHires.filter((hire) => !hire.graduatedAt)}
              />
            </Suspense>
          </TabsContent>
        </Tabs>
      </main>

      {/* Lazy load modals only when needed */}
      {showAddNewHire && (
        <Suspense fallback={null}>
          <AddNewHireModal 
            open={showAddNewHire}
            onOpenChange={handleCloseAddModal}
            trainers={trainers}
          />
        </Suspense>
      )}
      
      {showEditNewHire && editingNewHire && (
        <Suspense fallback={null}>
          <EditNewHireModal 
            newHire={editingNewHire}
            open={showEditNewHire}
            onOpenChange={handleCloseEditModal}
            trainers={trainers}
            onEditSuccess={fetchData}
          />
        </Suspense>
      )}
      
      {showAssignTrainer && selectedNewHire && (
        <Suspense fallback={null}>
          <AssignTrainerModal 
            newHire={selectedNewHire}
            open={showAssignTrainer}
            onOpenChange={handleCloseAssignModal}
            trainers={trainers}
            onAssignSuccess={fetchData}
          />
        </Suspense>
      )}

      <Dialog open={showLoginAccess} onOpenChange={handleCloseLoginAccess}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Prime Rep login access</DialogTitle>
            <DialogDescription>
              Share the relative sign-up link below. No password is created or
              shared here.
            </DialogDescription>
          </DialogHeader>

          {isLoadingLoginAccess && (
            <p className="py-4 text-sm text-muted-foreground">Checking login access…</p>
          )}
          {loginAccessError && (
            <div
              className="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-800"
              data-testid="login-access-error"
            >
              {loginAccessError}
            </div>
          )}
          {loginAccess && !loginAccessError && (
            <div className="space-y-4">
              <div className="rounded-md border bg-muted/40 p-3 text-sm">
                <p className="font-medium">{loginAccess.name}</p>
                <p className="text-muted-foreground" data-testid="login-access-email">
                  {loginAccess.email}
                </p>
              </div>
              <p className="text-sm text-muted-foreground">{loginAccess.instructions}</p>
              <div className="flex flex-wrap items-center gap-2">
                <Button asChild variant="outline" size="sm">
                  <a href={loginAccess.signupPath}>Open sign-up page</a>
                </Button>
                <Button
                  type="button"
                  variant="secondary"
                  size="sm"
                  onClick={handleCopySignupLink}
                  data-testid="copy-prime-rep-signup-link"
                >
                  <Copy className="w-4 h-4" />
                  Copy sign-up link
                </Button>
              </div>
              <p className="text-xs text-muted-foreground">
                Already registered?{" "}
                <a className="underline" href={loginAccess.signInPath}>Open sign-in</a>.
              </p>
            </div>
          )}

          <DialogFooter>
            {loginAccess?.invitationAvailable && (
              <Button
                type="button"
                onClick={handleSendInvitation}
                disabled={isSendingInvitation}
                isLoading={isSendingInvitation}
                data-testid="send-prime-rep-invitation"
              >
                <Send className="w-4 h-4" />
                {isSendingInvitation ? "Sending…" : "Send email invitation"}
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}