/**
 * Dealer Claim IO Tab
 * 
 * This component handles IO (Internal Order) management for dealer claims.
 * Located in: src/dealer-claim/components/request-detail/
 */

import { useState, useEffect, useMemo } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';
import { DollarSign, Download, CircleCheckBig, Target, CircleAlert } from 'lucide-react';
import { toast } from 'sonner';
import { validateIO, updateIODetails, getClaimDetails } from '@/services/dealerClaimApi';
import { useAuth } from '@/contexts/AuthContext';

interface IOTabProps {
  request: any;
  apiRequest?: any;
  onRefresh?: () => void;
}

interface IOBlockedDetails {
  ioNumber: string;
  blockedAmount: number;
  availableBalance: number; // Available amount before block
  remainingBalance: number; // Remaining amount after block
  blockedDate: string;
  blockedBy: string; // User who blocked
  sapDocumentNumber: string;
  status: 'blocked' | 'released' | 'failed' | 'pending';
}

export function IOTab({ request, apiRequest, onRefresh }: IOTabProps) {
  const { user } = useAuth();
  const requestId = apiRequest?.requestId || request?.requestId;

  // Get organizer user object from association (organizer) or fallback to organizedBy UUID
  const proposalDetails = apiRequest?.proposalDetails || {};
  const claimDetails = apiRequest?.claimDetails || apiRequest || {};

  // Calculate total base amount (needed for budget verification as requested)
  // This is the taxable amount excluding GST
  const totalBaseAmount = useMemo(() => {
    const costBreakupRaw = proposalDetails?.costBreakup || claimDetails?.costBreakup || [];
    const costBreakup = Array.isArray(costBreakupRaw)
      ? costBreakupRaw
      : (typeof costBreakupRaw === 'string'
        ? JSON.parse(costBreakupRaw)
        : []);

    if (!Array.isArray(costBreakup) || costBreakup.length === 0) {
      return Number(claimDetails?.totalProposedTaxableAmount || proposalDetails?.totalEstimatedBudget || proposalDetails?.total_estimated_budget || 0);
    }

    return costBreakup.reduce((sum: number, item: any) => {
      const amount = typeof item === 'object' ? (item.amount || 0) : 0;
      const quantity = typeof item === 'object' ? (item.quantity || 1) : 1;
      return sum + (Number(amount) * Number(quantity));
    }, 0);
  }, [proposalDetails?.costBreakup, claimDetails?.costBreakup, claimDetails?.totalProposedTaxableAmount, proposalDetails?.totalEstimatedBudget]);

  // Use base amount as the target budget for blocking
  const estimatedBudget = totalBaseAmount;

  // Budget status for signaling (Scenario 2)
  // Use apiRequest as the primary source of truth, fall back to request
  const budgetTracking = apiRequest?.budgetTracking || request?.budgetTracking || {};
  const budgetStatus = budgetTracking?.budgetStatus || budgetTracking?.budget_status || '';
  const internalOrdersList = apiRequest?.internalOrders || apiRequest?.internal_orders || request?.internalOrders || [];
  const isAdditionalBlockingNeeded = budgetStatus === 'PROPOSED' && internalOrdersList.length > 0;

  const [ioNumber, setIoNumber] = useState('');
  const [fetchingAmount, setFetchingAmount] = useState(false);
  const [fetchedAmount, setFetchedAmount] = useState<number | null>(null);
  const [amountToBlock, setAmountToBlock] = useState<string>('');
  const [blockedIOs, setBlockedIOs] = useState<IOBlockedDetails[]>([]);
  const [blockingBudget, setBlockingBudget] = useState(false);

  // Load existing IO blocks
  useEffect(() => {
    if (internalOrdersList.length > 0) {
      const formattedIOs = internalOrdersList.map((io: any) => {
        const org = io.organizer || null;
        const blockedByName = org?.displayName ||
          org?.display_name ||
          org?.name ||
          (org?.firstName && org?.lastName ? `${org.firstName} ${org.lastName}`.trim() : null) ||
          org?.email ||
          'Unknown User';
        return {
          ioNumber: io.ioNumber || io.io_number,
          blockedAmount: Number(io.ioBlockedAmount || io.io_blocked_amount || 0),
          availableBalance: Number(io.ioAvailableBalance || io.io_available_balance || 0),
          remainingBalance: Number(io.ioRemainingBalance || io.io_remaining_balance || 0),
          blockedDate: io.organizedAt || io.organized_at || new Date().toISOString(),
          blockedBy: blockedByName,
          sapDocumentNumber: io.sapDocumentNumber || io.sap_document_number || '',
          status: (io.status === 'BLOCKED' ? 'blocked' :
            io.status === 'RELEASED' ? 'released' :
              io.status === 'PENDING' ? 'pending' : 'blocked') as any,
        };
      });
      setBlockedIOs(formattedIOs);

      // If we are not in Scenario 2 (additional blocking), set the IO number from the last block for convenience
      if (!isAdditionalBlockingNeeded && formattedIOs.length > 0) {
        setIoNumber(formattedIOs[formattedIOs.length - 1].ioNumber);
      }
    }
  }, [apiRequest, request, isAdditionalBlockingNeeded, internalOrdersList]);

  /**
   * Fetch available budget from SAP
   * Validates IO number and gets available balance (returns dummy data for now)
   * Does not store anything in database - only validates
   */
  const handleFetchAmount = async () => {
    if (!ioNumber.trim()) {
      toast.error('Please enter an IO number');
      return;
    }

    if (!requestId) {
      toast.error('Request ID not found');
      return;
    }

    setFetchingAmount(true);
    try {
      // Call validate IO endpoint - returns dummy data for now, will integrate with SAP later
      const ioData = await validateIO(requestId, ioNumber.trim());

      if (ioData.isValid && ioData.availableBalance > 0) {
        setFetchedAmount(ioData.availableBalance);

        // Calculate total already blocked amount
        const totalAlreadyBlocked = blockedIOs.reduce((sum, io) => sum + io.blockedAmount, 0);

        // Calculate remaining budget to block
        const remainingToBlock = Math.max(0, estimatedBudget - totalAlreadyBlocked);

        // Pre-fill amount to block with remaining budget, otherwise use available balance
        if (remainingToBlock > 0) {
          setAmountToBlock(String(remainingToBlock.toFixed(2)));
        } else if (estimatedBudget > 0 && totalAlreadyBlocked === 0) {
          setAmountToBlock(String(estimatedBudget.toFixed(2)));
        } else {
          setAmountToBlock(String(ioData.availableBalance.toFixed(2)));
        }

        toast.success(`IO fetched from SAP. Available balance: ₹${ioData.availableBalance.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`);
      } else {
        toast.error('Invalid IO number or no available balance found');
        setFetchedAmount(null);
        setAmountToBlock('');
      }
    } catch (error: any) {
      console.error('Failed to fetch IO budget:', error);
      const errorMessage = error?.response?.data?.message || error?.message || 'Failed to validate IO number or fetch budget from SAP';
      toast.error(errorMessage);
      setFetchedAmount(null);
    } finally {
      setFetchingAmount(false);
    }
  };

  /**
   * Block budget in SAP system
   * This function:
   * 1. Validates the IO number and amount
   * 2. Calls SAP to block the budget
   * 3. Saves IO number, blocked amount, and balance details to database
   */
  const handleBlockBudget = async () => {
    if (!ioNumber.trim() || fetchedAmount === null) {
      toast.error('Please fetch IO amount first');
      return;
    }

    if (!requestId) {
      toast.error('Request ID not found');
      return;
    }

    const blockAmountRaw = parseFloat(amountToBlock);

    if (!amountToBlock || isNaN(blockAmountRaw) || blockAmountRaw <= 0) {
      toast.error('Please enter a valid amount to block');
      return;
    }

    // Round to exactly 2 decimal places to avoid floating point precision issues
    // Use parseFloat with toFixed to ensure exact 2 decimal precision
    const blockAmount = parseFloat(blockAmountRaw.toFixed(2));

    if (blockAmount > fetchedAmount) {
      toast.error('Amount to block exceeds available IO budget');
      return;
    }


    // Calculate total already blocked
    const totalAlreadyBlocked = blockedIOs.reduce((sum, io) => sum + io.blockedAmount, 0);
    const totalPlanned = totalAlreadyBlocked + blockAmount;

    // Validate that total planned must exactly match estimated budget
    if (estimatedBudget > 0) {
      const roundedEstimatedBudget = parseFloat(estimatedBudget.toFixed(2));
      const roundedTotalPlanned = parseFloat(totalPlanned.toFixed(2));

      if (Math.abs(roundedTotalPlanned - roundedEstimatedBudget) > 0.01) {
        toast.error(`Total blocked amount (₹${roundedTotalPlanned.toLocaleString('en-IN')}) must be exactly equal to the estimated budget (₹${roundedEstimatedBudget.toLocaleString('en-IN')})`);
        return;
      }
    }

    // Blocking budget

    setBlockingBudget(true);
    try {
      // Call updateIODetails with blockedAmount to block budget in SAP and store in database
      // This will store in internal_orders and claim_budget_tracking tables
      // Note: Backend will recalculate remainingBalance from SAP's response, so we pass it for reference only
      // Ensure all amounts are rounded to 2 decimal places for consistency
      const roundedFetchedAmount = parseFloat(fetchedAmount.toFixed(2));
      const calculatedRemaining = parseFloat((roundedFetchedAmount - blockAmount).toFixed(2));
      const payload = {
        ioNumber: ioNumber.trim(),
        ioAvailableBalance: roundedFetchedAmount,
        ioBlockedAmount: blockAmount,
        ioRemainingBalance: calculatedRemaining, // Calculated value (backend will use SAP's actual value)
      };

      // Sending to backend

      await updateIODetails(requestId, payload);

      // Fetch updated claim details to get the blocked IO data
      const claimData = await getClaimDetails(requestId);
      const updatedInternalOrder = claimData?.internalOrder || claimData?.internal_order;

      if (updatedInternalOrder) {
        const savedBlockedAmount = Number(updatedInternalOrder.ioBlockedAmount || updatedInternalOrder.io_blocked_amount || blockAmount);
        const savedRemainingBalance = Number(updatedInternalOrder.ioRemainingBalance || updatedInternalOrder.io_remaining_balance || 0);

        // Calculate expected remaining balance for validation/debugging
        const expectedRemainingBalance = fetchedAmount - savedBlockedAmount;

        // Blocking result processed

        // Warn if the saved amount differs from what we sent
        if (Math.abs(savedBlockedAmount - blockAmount) > 0.01) {
          console.warn('[IOTab] ⚠️ Amount mismatch! Sent:', blockAmount, 'Saved:', savedBlockedAmount);
        }

        // Warn if remaining balance calculation seems incorrect (for backend debugging)
        if (Math.abs(savedRemainingBalance - expectedRemainingBalance) > 0.01) {
          console.warn('[IOTab] ⚠️ Remaining balance calculation issue detected!', {
            availableBalance: fetchedAmount,
            blockedAmount: savedBlockedAmount,
            expectedRemaining: expectedRemainingBalance,
            backendRemaining: savedRemainingBalance,
            difference: savedRemainingBalance - expectedRemainingBalance,
          });
        }

        const currentUser = user as any;
        // When blocking, always use the current user who is performing the block action
        // The organizer association may be from initial IO organization, but we want who blocked the amount
        const blockedByName = currentUser?.displayName ||
          currentUser?.display_name ||
          currentUser?.name ||
          (currentUser?.firstName && currentUser?.lastName ? `${currentUser.firstName} ${currentUser.lastName}`.trim() : null) ||
          currentUser?.email ||
          'Current User';

        const blocked: IOBlockedDetails = {
          ioNumber: updatedInternalOrder.ioNumber || updatedInternalOrder.io_number || ioNumber,
          blockedAmount: savedBlockedAmount,
          availableBalance: fetchedAmount, // Available amount before block
          remainingBalance: savedRemainingBalance,
          blockedDate: updatedInternalOrder.organizedAt || updatedInternalOrder.organized_at || new Date().toISOString(),
          blockedBy: blockedByName,
          sapDocumentNumber: updatedInternalOrder.sapDocumentNumber || updatedInternalOrder.sap_document_number || '',
          status: 'blocked',
        };

        setBlockedIOs(prev => [...prev, blocked]);
        setAmountToBlock(''); // Clear the input
        setFetchedAmount(null); // Reset fetched state
        toast.success('IO budget blocked successfully in SAP');

        // Refresh request details
        onRefresh?.();
      } else {
        toast.error('IO blocked but failed to fetch updated details');
        onRefresh?.();
      }
    } catch (error: any) {
      console.error('Failed to block IO budget:', error);
      const errorMessage = error?.response?.data?.message || error?.message || 'Failed to block IO budget in SAP';
      toast.error(errorMessage);
    } finally {
      setBlockingBudget(false);
    }
  };

  return (
    <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
      {/* IO Budget Management Card */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            <DollarSign className="w-5 h-5 text-[#2d4a3e]" />
            IO Budget Management
          </CardTitle>
          <CardDescription>
            Enter IO number to fetch available budget from SAP
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-6">
          {/* IO Number Input */}
          <div className="space-y-3">
            <Label htmlFor="ioNumber">IO Number *</Label>
            <div className="flex gap-2">
              <Input
                id="ioNumber"
                placeholder="Enter IO number (e.g., IO-2024-12345)"
                value={ioNumber}
                onChange={(e) => setIoNumber(e.target.value)}
                disabled={fetchingAmount || (blockedIOs.length > 0 && !isAdditionalBlockingNeeded)}
                className="flex-1"
              />
              <Button
                onClick={handleFetchAmount}
                disabled={!ioNumber.trim() || fetchingAmount || (blockedIOs.length > 0 && !isAdditionalBlockingNeeded)}
                className="bg-[#2d4a3e] hover:bg-[#1f3329]"
              >
                <Download className="w-4 h-4 mr-2" />
                {fetchingAmount ? 'Fetching...' : 'Fetch Amount'}
              </Button>
            </div>
          </div>

          {/* Instructions when IO number is entered but not fetched */}
          {!fetchedAmount && blockedIOs.length === 0 && ioNumber.trim() && (
            <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
              <p className="text-sm text-blue-800">
                <strong>Next Step:</strong> Click "Fetch Amount" to validate the IO number and get available balance from SAP.
              </p>
            </div>
          )}

          {/* Fetched Amount Display */}
          {fetchedAmount !== null && (blockedIOs.length === 0 || isAdditionalBlockingNeeded) && (
            <>
              <div className="bg-green-50 border-2 border-green-200 rounded-lg p-4">
                <div className="flex items-center justify-between">
                  <div>
                    <p className="text-xs text-gray-600 uppercase tracking-wide mb-1">Available Amount</p>
                    <p className="text-2xl font-bold text-green-700">
                      ₹{fetchedAmount.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
                    </p>
                  </div>
                  <CircleCheckBig className="w-8 h-8 text-green-600" />
                </div>
                <div className="mt-3 pt-3 border-t border-green-200">
                  <p className="text-xs text-gray-600"><strong>IO Number:</strong> {ioNumber}</p>
                  <p className="text-xs text-gray-600 mt-1"><strong>Fetched from:</strong> SAP System</p>
                </div>
              </div>

              {/* Amount to Block Input */}
              <div className="space-y-3">
                <Label htmlFor="blockAmount">Amount to Block *</Label>
                <div className="relative">
                  <span className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500">₹</span>
                  <Input
                    type="number"
                    id="blockAmount"
                    placeholder="Enter amount to block"
                    min="0"
                    step="0.01"
                    value={amountToBlock}
                    onChange={(e) => setAmountToBlock(e.target.value)}
                    className="pl-8"
                  />
                </div>
                {estimatedBudget > 0 && (
                  <div className="bg-amber-50 border border-amber-200 rounded-lg p-3">
                    <p className="text-xs text-amber-800">
                      <strong>Required:</strong> Amount must be exactly equal to the estimated budget: <strong>₹{estimatedBudget.toLocaleString('en-IN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</strong>
                    </p>
                  </div>
                )}
              </div>

              {/* Block Button */}
              <Button
                onClick={handleBlockBudget}
                disabled={
                  blockingBudget ||
                  !amountToBlock ||
                  parseFloat(amountToBlock) <= 0 ||
                  parseFloat(amountToBlock) > fetchedAmount ||
                  (estimatedBudget > 0 && Math.abs((blockedIOs.reduce((s, i) => s + i.blockedAmount, 0) + parseFloat(amountToBlock)) - estimatedBudget) > 0.01)
                }
                className="w-full bg-[#2d4a3e] hover:bg-[#1f3329]"
              >
                <Target className="w-4 h-4 mr-2" />
                {blockingBudget ? 'Blocking in SAP...' : 'Block IO in SAP'}
              </Button>
            </>
          )}
        </CardContent>
      </Card>

      {/* IO Blocked Details Card */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            <CircleCheckBig className="w-5 h-5 text-green-600" />
            IO Blocked Details
          </CardTitle>
          <CardDescription>
            Details of IO blocked in SAP system
          </CardDescription>
        </CardHeader>
        <CardContent>
          {blockedIOs.length > 0 ? (
            <div className="space-y-6">
              {isAdditionalBlockingNeeded && (
                <div className="bg-amber-50 border-2 border-amber-500 rounded-lg p-4 animate-pulse">
                  <div className="flex items-start gap-3">
                    <CircleAlert className="w-6 h-6 text-amber-600 flex-shrink-0 mt-0.5" />
                    <div>
                      <p className="font-semibold text-amber-900">Additional Budget Blocking Required</p>
                      <p className="text-sm text-amber-700 mt-1">Actual expenses exceed the previously blocked amount. Please block an additional ₹{(estimatedBudget - blockedIOs.reduce((s, i) => s + i.blockedAmount, 0)).toLocaleString('en-IN', { minimumFractionDigits: 2 })}.</p>
                    </div>
                  </div>
                </div>
              )}

              {blockedIOs.slice().reverse().map((io, idx) => (
                <div key={idx} className="border rounded-lg overflow-hidden">
                  <div className={`p-3 flex justify-between items-center ${idx === 0 ? 'bg-green-50' : 'bg-gray-50'}`}>
                    <span className="font-semibold text-sm">IO: {io.ioNumber}</span>
                    <Badge className={
                      io.status === 'blocked' ? 'bg-green-100 text-green-800' :
                        io.status === 'pending' ? 'bg-amber-100 text-amber-800' :
                          'bg-blue-100 text-blue-800'
                    }>
                      {io.status === 'blocked' ? 'Blocked' :
                        io.status === 'pending' ? 'Provisioned' : 'Released'}
                    </Badge>
                  </div>
                  <div className="grid grid-cols-2 divide-x divide-y">
                    <div className="p-3">
                      <p className="text-[10px] text-gray-500 uppercase">Amount</p>
                      <p className="text-sm font-bold text-green-700">₹{io.blockedAmount.toLocaleString('en-IN')}</p>
                    </div>
                    <div className="p-3">
                      <p className="text-[10px] text-gray-500 uppercase">SAP Doc</p>
                      <p className="text-sm font-medium">{io.sapDocumentNumber || 'N/A'}</p>
                    </div>
                    <div className="p-3">
                      <p className="text-[10px] text-gray-500 uppercase">Blocked By</p>
                      <p className="text-xs">{io.blockedBy}</p>
                    </div>
                    <div className="p-3">
                      <p className="text-[10px] text-gray-500 uppercase">Date</p>
                      <p className="text-[10px]">{new Date(io.blockedDate).toLocaleString()}</p>
                    </div>
                  </div>
                </div>
              ))}

              <div className="mt-4 p-4 bg-[#2d4a3e] text-white rounded-lg flex justify-between items-center">
                <span className="font-bold">Total Blocked:</span>
                <span className="text-xl font-bold">₹{blockedIOs.reduce((s, i) => s + i.blockedAmount, 0).toLocaleString('en-IN', { minimumFractionDigits: 2 })}</span>
              </div>
            </div>
          ) : (
            <div className="text-center py-12">
              <DollarSign className="w-16 h-16 text-gray-300 mx-auto mb-4" />
              <p className="text-sm text-gray-500 mb-2">No IO blocked yet</p>
              <p className="text-xs text-gray-400">
                Enter IO number and fetch amount to block budget
              </p>
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  );
}
