import React, { useState, useMemo, useEffect } from 'react';
import { format } from 'date-fns';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Badge } from '@/components/ui/badge';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import {
  Package,
  User,
  Calendar,
  CheckCircle,
  Loader2,
  AlertCircle,
  Search,
  Plus,
  Minus,
} from 'lucide-react';
import {
  AssetRequest,
  AssetRequestAssignmentRequest,
  AssignedAssetDetail,
} from '@/types/asset-request';
import { Asset, AssetAssignment } from '@/types/asset-management';
import {
  validateAssignmentRequest,
  calculateInventoryImpact,
  logInventoryChange,
  createInventoryAuditLog,
} from '@/utils/inventoryManagement';

interface AssetRequestAssignmentProps {
  approvedRequests: AssetRequest[];
  availableAssets: Asset[];
  allAssets: Asset[];
  activeAssignments: AssetAssignment[];
  isLoading?: boolean;
  onAssign: (id: number, data: AssetRequestAssignmentRequest) => Promise<void>;
  currentUserId: number;
}

interface AssetAllocation {
  assetType: string;
  requestedQuantity: number;
  allocatedAssets: Asset[];
}

const AssetRequestAssignment: React.FC<AssetRequestAssignmentProps> = ({
  approvedRequests,
  availableAssets,
  allAssets,
  activeAssignments,
  isLoading = false,
  onAssign,
  currentUserId,
}) => {
  const [selectedRequest, setSelectedRequest] = useState<AssetRequest | null>(null);
  const [showAssignmentDialog, setShowAssignmentDialog] = useState(false);
  const [assetAllocations, setAssetAllocations] = useState<AssetAllocation[]>([]);
  const [searchTerm, setSearchTerm] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [filterAssetType, setFilterAssetType] = useState<string>('all');

  // Get unique asset types from available assets
  const assetTypes = useMemo(() => {
    const types = new Set(availableAssets.map((asset) => asset.assetType));
    return Array.from(types).sort();
  }, [availableAssets]);

  // Filter available assets based on search and type
  const filteredAvailableAssets = useMemo(() => {
    let filtered = [...availableAssets];

    if (filterAssetType !== 'all') {
      filtered = filtered.filter((asset) => asset.assetType === filterAssetType);
    }

    if (searchTerm) {
      const term = searchTerm.toLowerCase();
      filtered = filtered.filter(
        (asset) =>
          asset.assetCode.toLowerCase().includes(term) ||
          asset.assetType.toLowerCase().includes(term) ||
          asset.brandModel.toLowerCase().includes(term) ||
          asset.serialNumber.toLowerCase().includes(term)
      );
    }

    return filtered;
  }, [availableAssets, searchTerm, filterAssetType]);

  // Initialize allocations when a request is selected
  useEffect(() => {
    if (selectedRequest) {
      const allocations: AssetAllocation[] = selectedRequest.requestedAssets.map((item) => ({
        assetType: item.assetType,
        requestedQuantity: item.quantity,
        allocatedAssets: [],
      }));
      setAssetAllocations(allocations);
    }
  }, [selectedRequest]);

  const handleSelectRequest = (request: AssetRequest) => {
    setSelectedRequest(request);
    setShowAssignmentDialog(true);
    setSearchTerm('');
    setFilterAssetType('all');
  };

  const handleAddAsset = (asset: Asset, assetType: string) => {
    setAssetAllocations((prev) =>
      prev.map((allocation) => {
        if (allocation.assetType === assetType) {
          // Check if asset is already allocated
          if (allocation.allocatedAssets.some((a) => a.assetID === asset.assetID)) {
            return allocation;
          }
          // Check if we've reached the requested quantity
          if (allocation.allocatedAssets.length >= allocation.requestedQuantity) {
            return allocation;
          }
          return {
            ...allocation,
            allocatedAssets: [...allocation.allocatedAssets, asset],
          };
        }
        return allocation;
      })
    );
  };

  const handleRemoveAsset = (assetId: number, assetType: string) => {
    setAssetAllocations((prev) =>
      prev.map((allocation) => {
        if (allocation.assetType === assetType) {
          return {
            ...allocation,
            allocatedAssets: allocation.allocatedAssets.filter(
              (a) => a.assetID !== assetId
            ),
          };
        }
        return allocation;
      })
    );
  };

  const handleAssignSubmit = async () => {
    if (!selectedRequest) return;

    // Validate that all requested assets have been allocated
    const allAllocated = assetAllocations.every(
      (allocation) => allocation.allocatedAssets.length === allocation.requestedQuantity
    );

    if (!allAllocated) {
      return;
    }

    // Build assigned assets list
    const assignedAssets: AssignedAssetDetail[] = [];
    assetAllocations.forEach((allocation) => {
      allocation.allocatedAssets.forEach((asset) => {
        assignedAssets.push({
          assetID: asset.assetID,
          assetCode: asset.assetCode,
          assetType: asset.assetType,
          quantity: 1, // Each asset is assigned individually
        });
      });
    });

    // Validate assignment request
    const validation = validateAssignmentRequest(assignedAssets, allAssets, activeAssignments);
    
    if (!validation.valid) {
      console.error('Assignment validation failed:', validation.errors);
      alert(`Cannot assign assets:\n${validation.errors.join('\n')}`);
      return;
    }
    
    // Show warnings if any
    if (validation.warnings.length > 0) {
      const proceed = window.confirm(
        `Warning:\n${validation.warnings.join('\n')}\n\nDo you want to proceed with the assignment?`
      );
      if (!proceed) {
        return;
      }
    }

    // Calculate inventory impact
    const impact = calculateInventoryImpact(assignedAssets, allAssets, activeAssignments);
    console.log('Inventory impact:', impact);
    
    // Log each assignment for audit trail
    assignedAssets.forEach((asset) => {
      const auditLog = createInventoryAuditLog({
        action: 'assignment',
        assetType: asset.assetType,
        assetId: asset.assetID,
        assetCode: asset.assetCode,
        employeeId: selectedRequest.employeeID,
        employeeName: selectedRequest.employeeName,
        performedBy: currentUserId,
        previousState: 'available',
        newState: 'assigned',
        requestId: selectedRequest.requestID,
        remarks: `Assigned via asset request #${selectedRequest.requestID}`
      });
      logInventoryChange(auditLog);
    });

    setIsSubmitting(true);
    try {
      await onAssign(selectedRequest.requestID, {
        assignedAssets,
        assignedBy: currentUserId,
      });
      
      console.log('Assignment completed successfully');
      console.log('Updated inventory status:', impact);
      
      setShowAssignmentDialog(false);
      setSelectedRequest(null);
      setAssetAllocations([]);
    } catch (error) {
      console.error('Error assigning assets:', error);
      alert(`Failed to assign assets: ${error instanceof Error ? error.message : 'Unknown error'}`);
    } finally {
      setIsSubmitting(false);
    }
  };

  const isAssetAllocated = (assetId: number): boolean => {
    return assetAllocations.some((allocation) =>
      allocation.allocatedAssets.some((a) => a.assetID === assetId)
    );
  };

  const canAddMoreAssets = (assetType: string): boolean => {
    const allocation = assetAllocations.find((a) => a.assetType === assetType);
    if (!allocation) return false;
    return allocation.allocatedAssets.length < allocation.requestedQuantity;
  };

  const getAllocationProgress = (assetType: string): { current: number; total: number } => {
    const allocation = assetAllocations.find((a) => a.assetType === assetType);
    if (!allocation) return { current: 0, total: 0 };
    return {
      current: allocation.allocatedAssets.length,
      total: allocation.requestedQuantity,
    };
  };

  const isAllocationComplete = (): boolean => {
    return assetAllocations.every(
      (allocation) => allocation.allocatedAssets.length === allocation.requestedQuantity
    );
  };

  if (isLoading) {
    return (
      <Card>
        <CardContent className="flex items-center justify-center py-12">
          <Loader2 className="h-8 w-8 animate-spin text-primary" />
        </CardContent>
      </Card>
    );
  }

  return (
    <div className="space-y-4">
      <Card>
        <CardHeader>
          <CardTitle className="text-lg">Approved Requests - Assignment Queue</CardTitle>
        </CardHeader>
        <CardContent>
          {approvedRequests.length === 0 ? (
            <div className="flex flex-col items-center justify-center py-12 text-center">
              <Package className="h-12 w-12 text-muted-foreground mb-4" />
              <p className="text-muted-foreground">
                No approved requests waiting for asset assignment
              </p>
            </div>
          ) : (
            <div className="overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Request ID</TableHead>
                    <TableHead>Employee</TableHead>
                    <TableHead>Requested Assets</TableHead>
                    <TableHead>Approved Date</TableHead>
                    <TableHead className="text-right">Actions</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {approvedRequests.map((request) => (
                    <TableRow key={request.requestID}>
                      <TableCell className="font-medium">#{request.requestID}</TableCell>
                      <TableCell>
                        <div className="flex items-center gap-2">
                          <User className="h-4 w-4 text-muted-foreground" />
                          <span>{request.employeeName}</span>
                        </div>
                      </TableCell>
                      <TableCell>
                        <div className="space-y-1">
                          {request.requestedAssets.map((asset, idx) => (
                            <div key={idx} className="text-sm">
                              {asset.assetType} (x{asset.quantity})
                            </div>
                          ))}
                        </div>
                      </TableCell>
                      <TableCell>
                        {request.reviewedDate && (
                          <div className="flex items-center gap-2 text-sm">
                            <Calendar className="h-4 w-4 text-muted-foreground" />
                            <span>{format(new Date(request.reviewedDate), 'MMM dd, yyyy')}</span>
                          </div>
                        )}
                      </TableCell>
                      <TableCell className="text-right">
                        <Button
                          variant="default"
                          size="sm"
                          onClick={() => handleSelectRequest(request)}
                        >
                          <Package className="h-4 w-4 mr-2" />
                          Assign Assets
                        </Button>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Assignment Dialog */}
      <Dialog open={showAssignmentDialog} onOpenChange={setShowAssignmentDialog}>
        <DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Assign Assets to Request #{selectedRequest?.requestID}</DialogTitle>
            <DialogDescription>
              Select specific assets to assign to {selectedRequest?.employeeName}
            </DialogDescription>
          </DialogHeader>

          {selectedRequest && (
            <div className="space-y-6">
              {/* Request Summary */}
              <Card className="border-2">
                <CardHeader className="pb-3">
                  <CardTitle className="text-base">Request Summary</CardTitle>
                </CardHeader>
                <CardContent className="space-y-2">
                  <div className="grid grid-cols-2 gap-4 text-sm">
                    <div>
                      <span className="text-muted-foreground">Employee:</span>{' '}
                      <span className="font-medium">{selectedRequest.employeeName}</span>
                    </div>
                    <div>
                      <span className="text-muted-foreground">Submitted:</span>{' '}
                      <span className="font-medium">
                        {format(new Date(selectedRequest.submittedDate), 'MMM dd, yyyy')}
                      </span>
                    </div>
                  </div>
                  <div className="text-sm">
                    <span className="text-muted-foreground">Justification:</span>{' '}
                    <span>{selectedRequest.justification}</span>
                  </div>
                </CardContent>
              </Card>

              {/* Allocation Progress */}
              <div className="space-y-3">
                <h3 className="text-sm font-semibold">Allocation Progress</h3>
                {assetAllocations.map((allocation, idx) => {
                  const progress = getAllocationProgress(allocation.assetType);
                  const isComplete = progress.current === progress.total;

                  return (
                    <Card key={idx} className={isComplete ? 'border-green-500' : 'border-2'}>
                      <CardContent className="p-4">
                        <div className="flex items-center justify-between mb-3">
                          <div className="flex items-center gap-2">
                            <Package className="h-4 w-4" />
                            <span className="font-medium">{allocation.assetType}</span>
                          </div>
                          <Badge
                            className={
                              isComplete
                                ? 'bg-green-100 text-green-800 border-green-200'
                                : 'bg-yellow-100 text-yellow-800 border-yellow-200'
                            }
                          >
                            {progress.current}/{progress.total} Assigned
                          </Badge>
                        </div>

                        {/* Allocated Assets */}
                        {allocation.allocatedAssets.length > 0 && (
                          <div className="space-y-2">
                            {allocation.allocatedAssets.map((asset) => (
                              <div
                                key={asset.assetID}
                                className="flex items-center justify-between bg-muted/50 rounded p-2 text-sm"
                              >
                                <div>
                                  <span className="font-medium">{asset.assetCode}</span>
                                  <span className="text-muted-foreground ml-2">
                                    {asset.brandModel}
                                  </span>
                                </div>
                                <Button
                                  variant="ghost"
                                  size="sm"
                                  onClick={() =>
                                    handleRemoveAsset(asset.assetID, allocation.assetType)
                                  }
                                  className="h-7 w-7 p-0"
                                >
                                  <Minus className="h-4 w-4" />
                                </Button>
                              </div>
                            ))}
                          </div>
                        )}
                      </CardContent>
                    </Card>
                  );
                })}
              </div>

              {/* Asset Selection */}
              <div className="space-y-3">
                <h3 className="text-sm font-semibold">Available Assets</h3>

                {/* Filters */}
                <div className="flex gap-3">
                  <div className="relative flex-1">
                    <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
                    <Input
                      placeholder="Search by code, type, brand, or serial number..."
                      value={searchTerm}
                      onChange={(e) => setSearchTerm(e.target.value)}
                      className="pl-10"
                    />
                  </div>
                  <Select value={filterAssetType} onValueChange={setFilterAssetType}>
                    <SelectTrigger className="w-48">
                      <SelectValue placeholder="Filter by type" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="all">All Types</SelectItem>
                      {assetTypes.map((type) => (
                        <SelectItem key={type} value={type}>
                          {type}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                {/* Assets List */}
                <div className="border rounded-md max-h-64 overflow-y-auto">
                  {filteredAvailableAssets.length === 0 ? (
                    <div className="flex flex-col items-center justify-center py-8 text-center">
                      <AlertCircle className="h-8 w-8 text-muted-foreground mb-2" />
                      <p className="text-sm text-muted-foreground">
                        No available assets match your search
                      </p>
                    </div>
                  ) : (
                    <Table>
                      <TableHeader>
                        <TableRow>
                          <TableHead>Asset Code</TableHead>
                          <TableHead>Type</TableHead>
                          <TableHead>Brand/Model</TableHead>
                          <TableHead>Condition</TableHead>
                          <TableHead className="text-right">Action</TableHead>
                        </TableRow>
                      </TableHeader>
                      <TableBody>
                        {filteredAvailableAssets.map((asset) => {
                          const allocated = isAssetAllocated(asset.assetID);
                          const canAdd = canAddMoreAssets(asset.assetType);

                          return (
                            <TableRow key={asset.assetID}>
                              <TableCell className="font-medium">{asset.assetCode}</TableCell>
                              <TableCell>{asset.assetType}</TableCell>
                              <TableCell>{asset.brandModel}</TableCell>
                              <TableCell>
                                <Badge variant="outline">{asset.assetCondition}</Badge>
                              </TableCell>
                              <TableCell className="text-right">
                                {allocated ? (
                                  <Badge className="bg-green-100 text-green-800 border-green-200">
                                    <CheckCircle className="h-3 w-3 mr-1" />
                                    Allocated
                                  </Badge>
                                ) : (
                                  <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => handleAddAsset(asset, asset.assetType)}
                                    disabled={!canAdd}
                                  >
                                    <Plus className="h-4 w-4 mr-1" />
                                    Add
                                  </Button>
                                )}
                              </TableCell>
                            </TableRow>
                          );
                        })}
                      </TableBody>
                    </Table>
                  )}
                </div>
              </div>
            </div>
          )}

          <DialogFooter>
            <Button
              variant="outline"
              onClick={() => setShowAssignmentDialog(false)}
              disabled={isSubmitting}
            >
              Cancel
            </Button>
            <Button
              onClick={handleAssignSubmit}
              disabled={isSubmitting || !isAllocationComplete()}
              className="bg-green-600 hover:bg-green-700"
            >
              {isSubmitting ? (
                <>
                  <Loader2 className="h-4 w-4 mr-2 animate-spin" />
                  Assigning...
                </>
              ) : (
                <>
                  <CheckCircle className="h-4 w-4 mr-2" />
                  Confirm Assignment
                </>
              )}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
};

export default AssetRequestAssignment;
