import React, { useState } from 'react';
import { useAuth } from '@/lib/auth-context';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { Link } from 'react-router-dom';
import Layout from '@/components/layout/layout';
import { Card, CardContent } from '@/components/ui/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Package, Loader2, AlertCircle, Shield, Home } from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
  Breadcrumb,
  BreadcrumbList,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbPage,
  BreadcrumbSeparator,
} from '@/components/ui/breadcrumb';
import AssetRequestReview from '@/components/asset-request/AssetRequestReview';
import AssetRequestAssignment from '@/components/asset-request/AssetRequestAssignment';
import AssetRequestDashboard from '@/components/asset-request/AssetRequestDashboard';
import ErrorBoundary from '@/components/asset-request/ErrorBoundary';
import { ErrorDisplay } from '@/components/asset-request/ErrorDisplay';
import {
  AssetRequestReviewSkeleton,
  AssetRequestDashboardSkeleton,
  AssetRequestAssignmentSkeleton,
} from '@/components/asset-request/LoadingSkeletons';
import { assetRequestApi } from '@/services/assetRequestApi';
import { assetApi } from '@/services/assetApi';
import { assetAssignmentApi } from '@/services/assetAssignmentApi';
import {
  AssetRequestApprovalRequest,
  AssetRequestRejectionRequest,
  AssetRequestAssignmentRequest,
} from '@/types/asset-request';
import {
  notifyAdminApprovalSuccess,
  notifyAdminRejectionSuccess,
  notifyAdminAssignmentSuccess,
  notifyError,
} from '@/utils/assetRequestNotifications';

const AssetRequestManagementPage: React.FC = () => {
  const { userData } = useAuth();
  const queryClient = useQueryClient();
  const [activeTab, setActiveTab] = useState('pending');

  // Check if user is admin
  const isAdmin = userData?.roleId === 1 || userData?.roleName?.toLowerCase() === 'admin';

  // Get current user ID
  const currentUserId = userData?.employeeId || 0;

  // Fetch pending requests with availability
  const {
    data: pendingRequests = [],
    isLoading: isPendingLoading,
    error: pendingError,
    refetch: refetchPending,
  } = useQuery({
    queryKey: ['assetRequests', 'pending'],
    queryFn: () => assetRequestApi.getPending(),
    enabled: isAdmin,
    staleTime: 30000, // 30 seconds
    refetchInterval: 60000, // Refresh every minute
  });

  // Fetch all requests for dashboard
  const {
    data: allRequests = [],
    isLoading: isAllLoading,
    error: allError,
    refetch: refetchAll,
  } = useQuery({
    queryKey: ['assetRequests', 'all'],
    queryFn: () => assetRequestApi.getAll(),
    enabled: isAdmin,
    staleTime: 30000,
    refetchInterval: 60000,
  });

  // Fetch approved requests (for assignment queue)
  const approvedRequests = allRequests.filter((req) => req.status === 'approved');

  // Fetch available assets
  const {
    data: allAssets = [],
    isLoading: isAssetsLoading,
  } = useQuery({
    queryKey: ['assets', 'all'],
    queryFn: () => assetApi.getAll(),
    enabled: isAdmin,
    staleTime: 30000,
  });

  // Fetch all assignments to determine available assets
  const {
    data: allAssignments = [],
    isLoading: isAssignmentsLoading,
  } = useQuery({
    queryKey: ['assetAssignments', 'all'],
    queryFn: () => assetAssignmentApi.getAll(),
    enabled: isAdmin,
    staleTime: 30000,
  });

  // Filter available assets (not currently assigned)
  const availableAssets = allAssets.filter((asset) => {
    const activeAssignment = allAssignments.find(
      (assignment) => assignment.assetID === asset.assetID && !assignment.returnedDate
    );
    return !activeAssignment;
  });

  // Approve request mutation with optimistic updates
  const approveMutation = useMutation({
    mutationFn: ({ id, data }: { id: number; data: AssetRequestApprovalRequest }) =>
      assetRequestApi.approve(id, data),
    onMutate: async ({ id, data }) => {
      // Cancel outgoing refetches
      await queryClient.cancelQueries({ queryKey: ['assetRequests'] });

      // Snapshot previous values
      const previousPending = queryClient.getQueryData(['assetRequests', 'pending']);
      const previousAll = queryClient.getQueryData(['assetRequests', 'all']);

      // Optimistically update
      const updateRequest = (old: any) => {
        if (!old) return old;
        return old.map((req: any) =>
          req.requestID === id
            ? {
                ...req,
                status: 'approved',
                reviewedDate: new Date().toISOString(),
                reviewedBy: data.reviewedBy,
                reviewerName: userData ? `${userData.firstName} ${userData.lastName}` : '',
                adminComments: data.adminComments,
              }
            : req
        );
      };

      queryClient.setQueryData(['assetRequests', 'pending'], (old: any) =>
        old ? old.filter((req: any) => req.requestID !== id) : old
      );
      queryClient.setQueryData(['assetRequests', 'all'], updateRequest);

      return { previousPending, previousAll };
    },
    onSuccess: (updatedRequest) => {
      queryClient.invalidateQueries({ queryKey: ['assetRequests'] });
      notifyAdminApprovalSuccess(updatedRequest);
    },
    onError: (error: Error, _variables, context) => {
      // Rollback on error
      if (context?.previousPending) {
        queryClient.setQueryData(['assetRequests', 'pending'], context.previousPending);
      }
      if (context?.previousAll) {
        queryClient.setQueryData(['assetRequests', 'all'], context.previousAll);
      }
      notifyError('Approve Request', error.message || 'Failed to approve the request. Please try again.');
    },
  });

  // Reject request mutation with optimistic updates
  const rejectMutation = useMutation({
    mutationFn: ({ id, data }: { id: number; data: AssetRequestRejectionRequest }) =>
      assetRequestApi.reject(id, data),
    onMutate: async ({ id, data }) => {
      await queryClient.cancelQueries({ queryKey: ['assetRequests'] });

      const previousPending = queryClient.getQueryData(['assetRequests', 'pending']);
      const previousAll = queryClient.getQueryData(['assetRequests', 'all']);

      const updateRequest = (old: any) => {
        if (!old) return old;
        return old.map((req: any) =>
          req.requestID === id
            ? {
                ...req,
                status: 'rejected',
                reviewedDate: new Date().toISOString(),
                reviewedBy: data.reviewedBy,
                reviewerName: userData ? `${userData.firstName} ${userData.lastName}` : '',
                adminComments: data.adminComments,
              }
            : req
        );
      };

      queryClient.setQueryData(['assetRequests', 'pending'], (old: any) =>
        old ? old.filter((req: any) => req.requestID !== id) : old
      );
      queryClient.setQueryData(['assetRequests', 'all'], updateRequest);

      return { previousPending, previousAll };
    },
    onSuccess: (updatedRequest) => {
      queryClient.invalidateQueries({ queryKey: ['assetRequests'] });
      notifyAdminRejectionSuccess(updatedRequest);
    },
    onError: (error: Error, _variables, context) => {
      if (context?.previousPending) {
        queryClient.setQueryData(['assetRequests', 'pending'], context.previousPending);
      }
      if (context?.previousAll) {
        queryClient.setQueryData(['assetRequests', 'all'], context.previousAll);
      }
      notifyError('Reject Request', error.message || 'Failed to reject the request. Please try again.');
    },
  });

  // Add comment mutation
  const addCommentMutation = useMutation({
    mutationFn: ({ id, comments }: { id: number; comments: string }) =>
      assetRequestApi.addComment(id, {
        adminComments: comments,
        commentedBy: currentUserId,
      }),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['assetRequests'] });
      notifyAdminApprovalSuccess({ requestID: 0 } as any); // Use generic success toast
    },
    onError: (error: Error) => {
      notifyError('Add Comment', error.message || 'Failed to add comment. Please try again.');
    },
  });

  // Assign assets mutation with optimistic updates
  const assignMutation = useMutation({
    mutationFn: ({ id, data }: { id: number; data: AssetRequestAssignmentRequest }) =>
      assetRequestApi.assign(id, data),
    onMutate: async ({ id, data }) => {
      await queryClient.cancelQueries({ queryKey: ['assetRequests'] });
      await queryClient.cancelQueries({ queryKey: ['assets'] });
      await queryClient.cancelQueries({ queryKey: ['assetAssignments'] });

      const previousAll = queryClient.getQueryData(['assetRequests', 'all']);

      const updateRequest = (old: any) => {
        if (!old) return old;
        return old.map((req: any) =>
          req.requestID === id
            ? {
                ...req,
                status: 'assigned',
                assignedDate: new Date().toISOString(),
                assignedBy: data.assignedBy,
                assignerName: userData ? `${userData.firstName} ${userData.lastName}` : '',
              }
            : req
        );
      };

      queryClient.setQueryData(['assetRequests', 'all'], updateRequest);

      return { previousAll };
    },
    onSuccess: (updatedRequest) => {
      queryClient.invalidateQueries({ queryKey: ['assetRequests'] });
      queryClient.invalidateQueries({ queryKey: ['assets'] });
      queryClient.invalidateQueries({ queryKey: ['assetAssignments'] });
      notifyAdminAssignmentSuccess(updatedRequest);
    },
    onError: (error: Error, _variables, context) => {
      if (context?.previousAll) {
        queryClient.setQueryData(['assetRequests', 'all'], context.previousAll);
      }
      notifyError('Assign Assets', error.message || 'Failed to assign assets. Please try again.');
    },
  });

  const handleApprove = async (id: number, data: AssetRequestApprovalRequest) => {
    await approveMutation.mutateAsync({ id, data });
  };

  const handleReject = async (id: number, data: AssetRequestRejectionRequest) => {
    await rejectMutation.mutateAsync({ id, data });
  };

  const handleAddComment = async (id: number, comments: string) => {
    await addCommentMutation.mutateAsync({ id, comments });
  };

  const handleAssign = async (id: number, data: AssetRequestAssignmentRequest) => {
    await assignMutation.mutateAsync({ id, data });
  };

  const handleRetry = () => {
    refetchPending();
    refetchAll();
  };

  // Loading state
  if (!userData) {
    return (
      <Layout>
        <div className="flex items-center justify-center min-h-[400px]">
          <div className="text-center">
            <Loader2 className="h-8 w-8 animate-spin text-primary mx-auto mb-4" />
            <p className="text-muted-foreground">Loading user information...</p>
          </div>
        </div>
      </Layout>
    );
  }

  // Access denied for non-admin users
  if (!isAdmin) {
    return (
      <Layout>
        <div className="flex items-center justify-center min-h-[400px]">
          <Card className="max-w-md">
            <CardContent className="pt-6">
              <div className="text-center">
                <Shield className="h-12 w-12 text-destructive mx-auto mb-4" />
                <h2 className="text-xl font-semibold mb-2">Access Denied</h2>
                <p className="text-muted-foreground mb-4">
                  You do not have permission to access this page. Only administrators can
                  manage asset requests.
                </p>
                <Button onClick={() => window.history.back()}>Go Back</Button>
              </div>
            </CardContent>
          </Card>
        </div>
      </Layout>
    );
  }

  return (
    <Layout>
      {/* Breadcrumb Navigation */}
      <Breadcrumb className="mb-4">
        <BreadcrumbList>
          <BreadcrumbItem>
            <BreadcrumbLink asChild>
              <Link to="/dashboard" className="flex items-center gap-1">
                <Home className="h-4 w-4" />
                <span>Home</span>
              </Link>
            </BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbSeparator />
          <BreadcrumbItem>
            <BreadcrumbLink asChild>
              <Link to="/assets">Asset Management</Link>
            </BreadcrumbLink>
          </BreadcrumbItem>
          <BreadcrumbSeparator />
          <BreadcrumbItem>
            <BreadcrumbPage>Asset Request Management</BreadcrumbPage>
          </BreadcrumbItem>
        </BreadcrumbList>
      </Breadcrumb>

      {/* Page Header */}
      <div className="mb-6">
        <h1 className="text-2xl sm:text-3xl font-bold text-gray-900 flex items-center gap-2">
          <Package className="h-6 w-6 sm:h-8 sm:w-8 shrink-0" aria-hidden="true" />
          <span>Asset Request Management</span>
        </h1>
        <p className="text-muted-foreground mt-1 text-sm sm:text-base">
          Review, approve, and assign assets to employee requests
        </p>
      </div>

      {/* Error State */}
      {(pendingError || allError) && (
        <div className="mb-6">
          <ErrorDisplay
            error={pendingError || allError}
            title="Failed to Load Requests"
            onRetry={handleRetry}
            variant="card"
          />
        </div>
      )}

      {/* Tabbed Interface */}
      <Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-4">
        <TabsList className="grid w-full grid-cols-3">
          <TabsTrigger value="pending" className="relative">
            Pending Requests
            {pendingRequests.length > 0 && (
              <span className="ml-2 bg-yellow-500 text-white text-xs rounded-full px-2 py-0.5">
                {pendingRequests.length}
              </span>
            )}
          </TabsTrigger>
          <TabsTrigger value="all">All Requests</TabsTrigger>
          <TabsTrigger value="assignment" className="relative">
            Assignment Queue
            {approvedRequests.length > 0 && (
              <span className="ml-2 bg-green-500 text-white text-xs rounded-full px-2 py-0.5">
                {approvedRequests.length}
              </span>
            )}
          </TabsTrigger>
        </TabsList>

        {/* Pending Requests Tab */}
        <TabsContent value="pending">
          <ErrorBoundary onReset={refetchPending}>
            {isPendingLoading ? (
              <AssetRequestReviewSkeleton />
            ) : (
              <AssetRequestReview
                requests={pendingRequests}
                isLoading={isPendingLoading}
                onApprove={handleApprove}
                onReject={handleReject}
                onAddComment={handleAddComment}
                currentUserId={currentUserId}
              />
            )}
          </ErrorBoundary>
        </TabsContent>

        {/* All Requests Tab */}
        <TabsContent value="all">
          <ErrorBoundary onReset={refetchAll}>
            {isAllLoading ? (
              <AssetRequestDashboardSkeleton />
            ) : (
              <AssetRequestDashboard requests={allRequests} isLoading={isAllLoading} />
            )}
          </ErrorBoundary>
        </TabsContent>

        {/* Assignment Queue Tab */}
        <TabsContent value="assignment">
          <ErrorBoundary onReset={handleRetry}>
            {isAssetsLoading || isAssignmentsLoading ? (
              <AssetRequestAssignmentSkeleton />
            ) : (
              <AssetRequestAssignment
                approvedRequests={approvedRequests}
                availableAssets={availableAssets}
                allAssets={allAssets}
                activeAssignments={allAssignments.filter(a => !a.returnedDate)}
                isLoading={isAssetsLoading || isAssignmentsLoading}
                onAssign={handleAssign}
                currentUserId={currentUserId}
              />
            )}
          </ErrorBoundary>
        </TabsContent>
      </Tabs>
    </Layout>
  );
};

export default AssetRequestManagementPage;
