import { useState, useEffect, useMemo, useCallback } from 'react';
import workflowApi, { getPauseDetails } from '@/services/workflowApi';
import apiClient from '@/services/authApi';
import { getSocket } from '@/utils/socket';
import { isClaimManagementRequest } from '@/utils/claimRequestUtils';

/**
 * Custom Hook: useRequestDetails
 * 
 * Purpose: Manages request data fetching, transformation, and state management
 * 
 * Responsibilities:
 * - Fetches workflow details from API using request identifier (request number or UUID)
 * - Transforms backend data structure to frontend format
 * - Maps approval levels with TAT alerts
 * - Handles spectators and participants
 * - Provides refresh functionality
 * - Falls back to static databases when API fails
 * 
 * @param requestIdentifier - Request number or UUID to fetch
 * @param dynamicRequests - Optional array of dynamic requests for fallback
 * @param user - Current authenticated user object
 * @returns Object containing request data, loading state, refresh function, etc.
 */
export function useRequestDetails(
  requestIdentifier: string,
  dynamicRequests: any[] = [],
  user: any
) {
  // State: Stores the fetched and transformed request data
  const [apiRequest, setApiRequest] = useState<any | null>(null);

  // State: Indicates if data is currently being fetched
  const [refreshing, setRefreshing] = useState(false);

  // State: Loading state for initial fetch
  const [loading, setLoading] = useState(true);

  // State: Access denied information
  const [accessDenied, setAccessDenied] = useState<{ denied: boolean; message: string } | null>(null);

  // State: Stores the current approval level for the logged-in user
  const [currentApprovalLevel, setCurrentApprovalLevel] = useState<any | null>(null);

  // State: Indicates if the current user is a spectator (view-only access)
  const [isSpectator, setIsSpectator] = useState(false);

  /**
   * Helper: Convert name/email to initials for avatar display
   * Example: "John Doe" → "JD", "john@email.com" → "JO"
   */
  const toInitials = (name?: string, email?: string) => {
    const base = (name || email || 'NA').toString();
    return base.split(' ').map(s => s[0]).filter(Boolean).join('').slice(0, 2).toUpperCase();
  };

  /**
   * Helper: Map backend status strings to frontend display format
   * Converts: IN_PROGRESS → in-review, PENDING → pending, etc.
   */
  const statusMap = (s: string) => {
    const val = (s || '').toUpperCase();
    if (val === 'IN_PROGRESS') return 'in-review';
    if (val === 'PENDING') return 'pending';
    if (val === 'APPROVED') return 'approved';
    if (val === 'REJECTED') return 'rejected';
    if (val === 'CLOSED') return 'closed';
    if (val === 'SKIPPED') return 'skipped';
    return (s || '').toLowerCase();
  };

  /**
   * Function: refreshDetails
   * 
   * Purpose: Fetch the latest request data from backend and update all state
   * 
   * Process:
   * 1. Fetch workflow details from API
   * 2. Extract and validate data arrays (approvals, participants, documents, TAT alerts)
   * 3. Transform approval levels with TAT alerts
   * 4. Map spectators and documents
   * 5. Filter out TAT warning activities from audit trail
   * 6. Update all state with transformed data
   * 7. Determine current user's approval level and spectator status
   * 
   * Note: Wrapped in useCallback to allow use in Socket.io listeners
   */
  const refreshDetails = useCallback(async () => {
    setRefreshing(true);
    try {
      // API Call: Fetch complete workflow details including approvals, documents, participants
      const details = await workflowApi.getWorkflowDetails(requestIdentifier);
      if (!details) {
        console.warn('[useRequestDetails] No details returned from API');
        return;
      }

      // Extract: Separate data structures from API response
      const wf = details.workflow || {};
      const approvals = Array.isArray(details.approvals) ? details.approvals : [];
      const participants = Array.isArray(details.participants) ? details.participants : [];
      const documents = Array.isArray(details.documents) ? details.documents : [];
      const summary = details.summary || {};
      const tatAlerts = Array.isArray(details.tatAlerts) ? details.tatAlerts : [];

      // Debug: Log TAT alerts for monitoring
      if (tatAlerts.length > 0) {
        // TAT alerts loaded - logging removed
      }

      const currentLevel = summary?.currentLevel || wf.currentLevel || 1;

      /**
       * Transform: Map approval levels to UI format with TAT alerts
       * Each approval level includes:
       * - Display status (waiting, pending, in-review, approved, rejected, skipped)
       * - TAT information (hours, elapsed, remaining, percentage)
       * - TAT alerts specific to this level
       * - Approver details
       */
      const approvalFlow = approvals.map((a: any) => {
        const levelNumber = a.levelNumber || 0;
        const levelStatus = (a.status || '').toString().toUpperCase();
        const levelId = a.levelId || a.level_id;

        // Determine display status based on workflow progress
        let displayStatus = statusMap(a.status);

        // Future levels that haven't been reached yet show as "waiting"
        if (levelNumber > currentLevel && levelStatus !== 'APPROVED' && levelStatus !== 'REJECTED') {
          displayStatus = 'waiting';
        }
        // Current level with pending status shows as "pending"
        else if (levelNumber === currentLevel && levelStatus === 'PENDING') {
          displayStatus = 'pending';
        }

        // Filter: Get TAT alerts that belong to this specific approval level
        const levelAlerts = tatAlerts.filter((alert: any) => alert.levelId === levelId);

        return {
          step: levelNumber,
          levelId,
          role: a.levelName || a.approverName || 'Approver',
          status: displayStatus,
          approver: a.approverName || a.approverEmail,
          approverId: a.approverId || a.approver_id,
          approverEmail: a.approverEmail,
          tatHours: Number(a.tatHours || 0),
          elapsedHours: Number(a.elapsedHours || 0),
          remainingHours: Number(a.remainingHours || 0),
          tatPercentageUsed: Number(a.tatPercentageUsed || 0),
          // Calculate actual hours taken if level is completed
          actualHours: a.levelEndTime && a.levelStartTime
            ? Math.max(0, (new Date(a.levelEndTime).getTime() - new Date(a.levelStartTime).getTime()) / (1000 * 60 * 60))
            : undefined,
          comment: a.comments || undefined,
          timestamp: a.actionDate || undefined,
          levelStartTime: a.levelStartTime || a.tatStartTime,
          tatAlerts: levelAlerts,
          skipReason: a.skipReason || undefined,
          isSkipped: levelStatus === 'SKIPPED' || a.isSkipped || false,
        };
      });

      /**
       * Transform: Map spectators from participants array
       * Spectators have view-only access to the request
       */
      const spectators = participants
        .filter((p: any) => (p.participantType || p.participant_type || '').toUpperCase() === 'SPECTATOR')
        .map((p: any) => ({
          name: p.userName || p.user_name || p.userEmail || p.user_email,
          role: 'Spectator',
          email: p.userEmail || p.user_email,
          avatar: toInitials(p.userName || p.user_name, p.userEmail || p.user_email),
        }));

      /**
       * Helper: Get participant name by userId
       * Used for document upload attribution
       */
      const participantNameById = (uid?: string) => {
        if (!uid) return undefined;
        const p = participants.find((x: any) => x.userId === uid || x.user_id === uid);
        if (p?.userName || p?.user_name) return p.userName || p.user_name;
        if (wf.initiatorId === uid) return wf.initiator?.displayName || wf.initiator?.email;
        return uid;
      };

      /**
       * Transform: Map documents with file size conversion and uploader details
       * Converts bytes to MB for better readability
       */
      const mappedDocuments = documents.map((d: any) => {
        const sizeBytes = Number(d.fileSize || d.file_size || 0);
        const sizeMb = (sizeBytes / (1024 * 1024)).toFixed(2) + ' MB';
        return {
          documentId: d.documentId || d.document_id,
          name: d.originalFileName || d.fileName || d.file_name,
          fileType: d.fileType || d.file_type || '',
          size: sizeMb,
          sizeBytes: sizeBytes,
          uploadedBy: participantNameById(d.uploadedBy || d.uploaded_by),
          uploadedAt: d.uploadedAt || d.uploaded_at,
        };
      });

      /**
       * Filter: Remove TAT breach activities from audit trail
       * TAT warnings are already shown in approval steps, no need to duplicate in timeline
       */
      const filteredActivities = Array.isArray(details.activities)
        ? details.activities.filter((activity: any) => {
          const activityType = (activity.type || '').toLowerCase();
          return activityType !== 'sla_warning';
        })
        : [];

      /**
       * Fetch: Get pause details only if request is actually paused
       * Use request-level isPaused field from workflow response
       */
      let pauseInfo = null;
      const isPaused = (wf as any).isPaused || false;

      if (isPaused) {
        try {
          pauseInfo = await getPauseDetails(wf.requestId);
        } catch (error) {
          // Pause info not available - ignore
        }
      }

      /**
       * Fetch: Get claim details if this is a claim management request
       */
      let claimDetails = null;
      let proposalDetails = null;
      let completionDetails = null;
      let internalOrder = null;
      let internalOrders = [];
      let creditNoteWfmData = null;

      if (isClaimManagementRequest(wf)) {
        // Fetch Credit Note independently
        try {
          const cnResponse = await apiClient.get(`/dealer-claims/${wf.requestId}/credit-note-wfm`);
          const responseData = cnResponse.data ?? cnResponse;
          creditNoteWfmData = Array.isArray(responseData?.data) ? responseData.data : (Array.isArray(responseData) ? responseData : []);
        } catch (cnError) {
          console.warn('[useRequestDetails] Error fetching credit note WFM data:', cnError);
        }

        try {
          const claimResponse = await apiClient.get(`/dealer-claims/${wf.requestId}`);

          const claimData = claimResponse.data?.data || claimResponse.data;

          if (claimData) {
            claimDetails = claimData.claimDetails || claimData.claim_details;
            proposalDetails = claimData.proposalDetails || claimData.proposal_details;
            completionDetails = claimData.completionDetails || claimData.completion_details;
            internalOrder = claimData.internalOrder || claimData.internal_order || null;
            internalOrders = claimData.internalOrders || claimData.internal_orders || [];
            // New normalized tables
            const budgetTracking = claimData.budgetTracking || claimData.budget_tracking || null;
            const invoice = claimData.invoice || null;
            const creditNote = claimData.creditNote || claimData.credit_note || null;
            const completionExpenses = claimData.completionExpenses || claimData.completion_expenses || null;

            // Store new fields in claimDetails for backward compatibility and easy access
            if (claimDetails) {
              (claimDetails as any).budgetTracking = budgetTracking;
              (claimDetails as any).invoice = invoice;
              (claimDetails as any).creditNote = creditNote;
              (claimDetails as any).completionExpenses = completionExpenses;
              (claimDetails as any).creditNoteWfmData = creditNoteWfmData;
            }

            // Extracted details processed
          } else {
            console.warn('[useRequestDetails] No claimData found in response');
          }
        } catch (error: any) {
          // Claim details not available - request might not be fully initialized yet
          console.error('[useRequestDetails] Error fetching claim details:', {
            error: error?.message || error,
            status: error?.response?.status,
            statusText: error?.response?.statusText,
            responseData: error?.response?.data,
            requestId: wf.requestId,
          });
        }
      }

      /**
       * Build: Complete request object with all transformed data
       * This object is used throughout the UI
       */
      const updatedRequest = {
        ...wf,
        id: wf.requestNumber || wf.requestId,
        requestId: wf.requestId, // UUID for API calls
        requestNumber: wf.requestNumber, // Human-readable number for display
        initiatorId: wf.initiatorId || wf.initiator_id,
        title: wf.title,
        description: wf.description,
        status: statusMap(wf.status),
        priority: (wf.priority || '').toString().toLowerCase(),
        workflowType: wf.workflowType || (wf.templateType === 'claim-management' ? 'CLAIM_MANAGEMENT' : 'NON_TEMPLATIZED'),
        approvalFlow,
        approvals, // Raw approvals for SLA calculations
        participants,
        documents: mappedDocuments,
        spectators,
        summary, // Backend-provided SLA summary
        // Ensure SLA is available at root level for RequestDetailHeader
        // Backend provides full SLA in summary.sla with all required fields
        sla: summary?.sla || wf.sla || null,
        initiator: {
          userId: wf.initiator?.userId || wf.initiator?.user_id || wf.initiatorId || wf.initiator_id,
          name: wf.initiator?.displayName || wf.initiator?.email,
          role: wf.initiator?.designation || undefined,
          department: wf.initiator?.department || undefined,
          email: wf.initiator?.email || undefined,
          phone: wf.initiator?.phone || undefined,
          avatar: toInitials(wf.initiator?.displayName, wf.initiator?.email),
        },
        createdAt: wf.createdAt,
        updatedAt: wf.updatedAt,
        totalSteps: wf.totalLevels || 1,
        // Store both raw and clamped values - raw for completion detection, clamped for display
        currentStepRaw: summary?.currentLevel || wf.currentLevel || 1,
        currentStep: Math.min(Math.max(1, summary?.currentLevel || wf.currentLevel || 1), wf.totalLevels || 1),
        auditTrail: filteredActivities,
        conclusionRemark: wf.conclusionRemark || null,
        closureDate: wf.closureDate || null,
        pauseInfo: pauseInfo || null, // Include pause info for resume/retrigger buttons
        // Claim management specific data
        claimDetails: claimDetails || null,
        proposalDetails: proposalDetails || null,
        completionDetails: completionDetails || null,
        internalOrder: internalOrder || null,
        internalOrders: internalOrders || [],
        // New normalized tables (also available via claimDetails for backward compatibility)
        budgetTracking: (claimDetails as any)?.budgetTracking || null,
        invoice: claimDetails?.invoice || (claimDetails as any)?.invoice || null,
        creditNote: (claimDetails as any)?.creditNote || null,
        creditNoteWfmData: creditNoteWfmData || (claimDetails as any)?.creditNoteWfmData || null,
        completionExpenses: (claimDetails as any)?.completionExpenses || null,
        templateType: wf.templateType || wf.template_type,
        form16Submission: details.form16Submission || null,
      };

      setApiRequest(updatedRequest);

      /**
       * Determine: Find the approval level assigned to current user
       * Used to show approve/reject buttons only when user is the CURRENT active approver
       * Conditions:
       * 1. User email matches approverEmail
       * 2. Status is PENDING or IN_PROGRESS
       * 3. Approval level number matches the current active level in workflow
       */
      const userEmail = (user as any)?.email?.toLowerCase();
      const newCurrentLevel = approvals.find((a: any) => {
        const st = (a.status || '').toString().toUpperCase();
        const approverEmail = (a.approverEmail || '').toLowerCase();
        const approvalLevelNumber = a.levelNumber || 0;
        // Only show buttons if user is assigned to the CURRENT active level
        // Include PAUSED status - paused level is still the current level
        return (st === 'PENDING' || st === 'IN_PROGRESS' || st === 'PAUSED')
          && approverEmail === userEmail
          && approvalLevelNumber === currentLevel;
      });
      setCurrentApprovalLevel(newCurrentLevel || null);

      /**
       * Determine: Check if current user is a spectator
       * Spectators can only view and comment, cannot approve/reject
       */
      const viewerId = (user as any)?.userId;
      if (viewerId) {
        const isSpec = participants.some((p: any) =>
          (p.participantType || p.participant_type || '').toUpperCase() === 'SPECTATOR' &&
          (p.userId || p.user_id) === viewerId
        );
        setIsSpectator(isSpec);
      } else {
        setIsSpectator(false);
      }
    } catch (error) {
      console.error('[useRequestDetails] Error refreshing details:', error);
      alert('Failed to refresh request details. Please try again.');
    } finally {
      setRefreshing(false);
    }
  }, [requestIdentifier, user]); // useCallback dependencies

  /**
   * Effect: Initial data fetch when component mounts or requestIdentifier changes
   * This is the primary data loading mechanism
   */
  useEffect(() => {
    if (!requestIdentifier) {
      setLoading(false);
      return;
    }

    let mounted = true;
    setLoading(true);
    setAccessDenied(null);

    (async () => {
      try {
        const details = await workflowApi.getWorkflowDetails(requestIdentifier);
        if (!mounted || !details) {
          if (mounted) setLoading(false);
          return;
        }

        // Use the same transformation logic as refreshDetails
        const wf = details.workflow || {};
        const approvals = Array.isArray(details.approvals) ? details.approvals : [];
        const participants = Array.isArray(details.participants) ? details.participants : [];
        const documents = Array.isArray(details.documents) ? details.documents : [];
        const summary = details.summary || {};
        const tatAlerts = Array.isArray(details.tatAlerts) ? details.tatAlerts : [];

        // TAT alerts received - logging removed

        const priority = (wf.priority || '').toString().toLowerCase();
        const currentLevel = summary?.currentLevel || wf.currentLevel || 1;

        // Transform approval flow (same logic as refreshDetails)
        const approvalFlow = approvals.map((a: any) => {
          const levelNumber = a.levelNumber || 0;
          const levelStatus = (a.status || '').toString().toUpperCase();
          const levelId = a.levelId || a.level_id;

          let displayStatus = statusMap(a.status);

          // If paused, show paused status (don't change it)
          if (levelStatus === 'PAUSED') {
            displayStatus = 'paused';
          } else if (levelNumber > currentLevel && levelStatus !== 'APPROVED' && levelStatus !== 'REJECTED') {
            displayStatus = 'waiting';
          } else if (levelNumber === currentLevel && (levelStatus === 'PENDING' || levelStatus === 'IN_PROGRESS')) {
            displayStatus = levelStatus === 'IN_PROGRESS' ? 'in-review' : 'pending';
          }

          const levelAlerts = tatAlerts.filter((alert: any) => alert.levelId === levelId);

          return {
            step: levelNumber,
            levelId,
            role: a.levelName || a.approverName || 'Approver',
            status: displayStatus,
            approver: a.approverName || a.approverEmail,
            approverId: a.approverId || a.approver_id,
            approverEmail: a.approverEmail,
            tatHours: Number(a.tatHours || 0),
            elapsedHours: Number(a.elapsedHours || 0),
            remainingHours: Number(a.remainingHours || 0),
            tatPercentageUsed: Number(a.tatPercentageUsed || 0),
            // Use backend-calculated elapsedHours (working hours) for completed approvals
            // Backend already calculates this correctly using calculateElapsedWorkingHours
            actualHours: a.elapsedHours !== undefined && a.elapsedHours !== null
              ? Number(a.elapsedHours)
              : undefined,
            comment: a.comments || undefined,
            timestamp: a.actionDate || undefined,
            levelStartTime: a.levelStartTime || a.tatStartTime,
            tatAlerts: levelAlerts,
          };
        });

        // Map spectators
        const spectators = participants
          .filter((p: any) => (p.participantType || '').toUpperCase() === 'SPECTATOR')
          .map((p: any) => ({
            name: p.userName || p.userEmail,
            role: 'Spectator',
            avatar: toInitials(p.userName, p.userEmail),
          }));

        // Helper to get participant name by ID
        const participantNameById = (uid?: string) => {
          if (!uid) return undefined;
          const p = participants.find((x: any) => x.userId === uid);
          if (p?.userName) return p.userName;
          if (wf.initiatorId === uid) return wf.initiator?.displayName || wf.initiator?.email;
          return uid;
        };

        // Map documents with size conversion
        const mappedDocuments = documents.map((d: any) => {
          const sizeBytes = Number(d.fileSize || 0);
          const sizeMb = (sizeBytes / (1024 * 1024)).toFixed(2) + ' MB';
          return {
            documentId: d.documentId || d.document_id,
            name: d.originalFileName || d.fileName,
            fileType: d.fileType || d.file_type || '',
            size: sizeMb,
            sizeBytes: sizeBytes,
            uploadedBy: participantNameById(d.uploadedBy),
            uploadedAt: d.uploadedAt,
          };
        });

        // Filter out TAT warnings from activities
        const filteredActivities = Array.isArray(details.activities)
          ? details.activities.filter((activity: any) => {
            const activityType = (activity.type || '').toLowerCase();
            return activityType !== 'sla_warning';
          })
          : [];

        // Fetch pause details only if request is actually paused
        // Use request-level isPaused field from workflow response
        let pauseInfo = null;
        const isPaused = (wf as any).isPaused || false;

        if (isPaused) {
          try {
            pauseInfo = await getPauseDetails(wf.requestId);
          } catch (error) {
            // Pause info not available - ignore
          }
        }

        /**
         * Fetch: Get claim details if this is a claim management request
         */
        let claimDetails = null;
        let proposalDetails = null;
        let completionDetails = null;
        let internalOrder = null;
        let internalOrders = [];
        let creditNoteWfmData = null;

        if (isClaimManagementRequest(wf)) {
          // Fetch Credit Note independently
          try {
            const cnResponse = await apiClient.get(`/dealer-claims/${wf.requestId}/credit-note-wfm`);
            const responseData = cnResponse.data ?? cnResponse;
            creditNoteWfmData = Array.isArray(responseData?.data) ? responseData.data : (Array.isArray(responseData) ? responseData : []);
          } catch (cnError) {
            console.warn('[useRequestDetails] Error fetching credit note WFM data:', cnError);
          }

          try {
            const claimResponse = await apiClient.get(`/dealer-claims/${wf.requestId}`);

            const claimData = claimResponse.data?.data || claimResponse.data;
            if (claimData) {
              claimDetails = claimData.claimDetails || claimData.claim_details;
              proposalDetails = claimData.proposalDetails || claimData.proposal_details;
              completionDetails = claimData.completionDetails || claimData.completion_details;
              internalOrder = claimData.internalOrder || claimData.internal_order || null;
              internalOrders = claimData.internalOrders || claimData.internal_orders || [];
              // New normalized tables
              const budgetTracking = claimData.budgetTracking || claimData.budget_tracking || null;
              const invoice = claimData.invoice || null;
              const creditNote = claimData.creditNote || claimData.credit_note || null;
              const completionExpenses = claimData.completionExpenses || claimData.completion_expenses || null;

              // Store new fields in claimDetails for backward compatibility and easy access
              if (claimDetails) {
                (claimDetails as any).budgetTracking = budgetTracking;
                (claimDetails as any).invoice = invoice;
                (claimDetails as any).creditNote = creditNote;
                (claimDetails as any).completionExpenses = completionExpenses;
                (claimDetails as any).creditNoteWfmData = creditNoteWfmData;
              }

              // Initial load - Extracted details processed
            }
          } catch (error: any) {
            // Claim details not available - request might not be fully initialized yet
            console.error('[useRequestDetails] Initial load - Error fetching claim details:', {
              error: error?.message || error,
              status: error?.response?.status,
              requestId: wf.requestId,
            });
          }
        }

        // Build complete request object
        const mapped = {
          id: wf.requestNumber || wf.requestId,
          requestId: wf.requestId,
          title: wf.title,
          description: wf.description,
          priority,
          status: statusMap(wf.status),
          workflowType: wf.workflowType || (wf.templateType === 'claim-management' ? 'CLAIM_MANAGEMENT' : 'NON_TEMPLATIZED'),
          summary,
          initiator: {
            name: wf.initiator?.displayName || wf.initiator?.email,
            role: wf.initiator?.designation || undefined,
            department: wf.initiator?.department || undefined,
            email: wf.initiator?.email || undefined,
            phone: wf.initiator?.phone || undefined,
            avatar: toInitials(wf.initiator?.displayName, wf.initiator?.email),
          },
          createdAt: wf.createdAt,
          updatedAt: wf.updatedAt,
          totalSteps: wf.totalLevels || 1,
          // Store both raw and clamped values - raw for completion detection, clamped for display
          currentStepRaw: summary?.currentLevel || wf.currentLevel || 1,
          currentStep: Math.min(Math.max(1, summary?.currentLevel || wf.currentLevel || 1), wf.totalLevels || 1),
          approvalFlow,
          approvals,
          documents: mappedDocuments,
          spectators,
          auditTrail: filteredActivities,
          conclusionRemark: wf.conclusionRemark || null,
          closureDate: wf.closureDate || null,
          pauseInfo: pauseInfo || null,
          // Claim management specific data
          claimDetails: claimDetails || null,
          proposalDetails: proposalDetails || null,
          completionDetails: completionDetails || null,
          internalOrder: internalOrder || null,
          internalOrders: internalOrders || [],
          // New normalized tables (also available via claimDetails for backward compatibility)
          budgetTracking: (claimDetails as any)?.budgetTracking || null,
          invoice: (claimDetails as any)?.invoice || null,
          creditNote: (claimDetails as any)?.creditNote || null,
          creditNoteWfmData: creditNoteWfmData || (claimDetails as any)?.creditNoteWfmData || null,
          completionExpenses: (claimDetails as any)?.completionExpenses || null,
          templateType: wf.templateType || wf.template_type,
          form16Submission: details.form16Submission || null,
        };

        setApiRequest(mapped);

        // Find current user's approval level
        // Only show approve/reject buttons if user is the CURRENT active approver
        // Include PAUSED status - when paused, the paused level is still the current level
        const userEmail = (user as any)?.email?.toLowerCase();
        const userCurrentLevel = approvals.find((a: any) => {
          const status = (a.status || '').toString().toUpperCase();
          const approverEmail = (a.approverEmail || '').toLowerCase();
          const approvalLevelNumber = a.levelNumber || 0;
          // Only show buttons if user is assigned to the CURRENT active level
          // Include PAUSED status - paused level is still the current level
          return (status === 'PENDING' || status === 'IN_PROGRESS' || status === 'PAUSED')
            && approverEmail === userEmail
            && approvalLevelNumber === currentLevel;
        });
        setCurrentApprovalLevel(userCurrentLevel || null);

        // Check spectator status
        const viewerId = (user as any)?.userId;
        if (viewerId) {
          const isSpec = participants.some((p: any) =>
            (p.participantType || '').toUpperCase() === 'SPECTATOR' && p.userId === viewerId
          );
          setIsSpectator(isSpec);
        } else {
          setIsSpectator(false);
        }
      } catch (error: any) {
        console.error('[useRequestDetails] Error loading request details:', error);
        if (mounted) {
          // Check for 403 Forbidden (Access Denied)
          if (error?.response?.status === 403) {
            const message = error?.response?.data?.message ||
              'You do not have permission to view this request. Access is restricted to the initiator, approvers, and spectators of this request.';
            setAccessDenied({ denied: true, message });
          }
          setApiRequest(null);
        }
      } finally {
        if (mounted) {
          setLoading(false);
        }
      }
    })();

    return () => { mounted = false; };
  }, [requestIdentifier, user]);

  /**
   * Computed: Get final request object with fallback to static databases
   * Priority: API data → Custom Database → Claim Database → Dynamic props → null
   */
  const request = useMemo(() => {
    // Primary source: API data
    if (apiRequest) return apiRequest;

    // Fallback: Dynamic requests passed as props
    const dynamicRequest = dynamicRequests.find((req: any) =>
      req.id === requestIdentifier ||
      req.requestNumber === requestIdentifier ||
      req.request_number === requestIdentifier
    );
    if (dynamicRequest) return dynamicRequest;

    return null;
  }, [requestIdentifier, dynamicRequests, apiRequest]);

  /**
   * Computed: Check if current user is the request initiator
   * Initiators have special permissions (add approvers, skip approvers, close request)
   */
  const isInitiator = useMemo(() => {
    if (!request || !user) return false;
    const userEmail = (user as any)?.email?.toLowerCase();
    const initiatorEmail = request.initiator?.email?.toLowerCase();
    return userEmail === initiatorEmail;
  }, [request, user]);

  /**
   * Computed: Get all existing participants for validation
   * Used when adding new approvers/spectators to prevent duplicates
   */
  const existingParticipants = useMemo(() => {
    if (!request) return [];

    const participants: Array<{ email: string; participantType: string; name?: string }> = [];

    // Add initiator
    if (request.initiator?.email) {
      participants.push({
        email: request.initiator.email.toLowerCase(),
        participantType: 'INITIATOR',
        name: request.initiator.name
      });
    }

    // Add approvers from approval flow
    if (request.approvalFlow && Array.isArray(request.approvalFlow)) {
      request.approvalFlow.forEach((approval: any) => {
        if (approval.approverEmail) {
          participants.push({
            email: approval.approverEmail.toLowerCase(),
            participantType: 'APPROVER',
            name: approval.approver
          });
        }
      });
    }

    // Add spectators
    if (request.spectators && Array.isArray(request.spectators)) {
      request.spectators.forEach((spectator: any) => {
        if (spectator.email) {
          participants.push({
            email: spectator.email.toLowerCase(),
            participantType: 'SPECTATOR',
            name: spectator.name
          });
        }
      });
    }

    // Add from participants array
    if (request.participants && Array.isArray(request.participants)) {
      request.participants.forEach((p: any) => {
        const email = (p.userEmail || p.email || '').toLowerCase();
        const participantType = (p.participantType || p.participant_type || '').toUpperCase();
        const name = p.userName || p.user_name || p.name;

        if (email && participantType && !participants.find(x => x.email === email)) {
          participants.push({ email, participantType, name });
        }
      });
    }

    return participants;
  }, [request]);

  /**
   * Effect: Listen for real-time request updates via Socket.io
   * 
   * Purpose: Auto-refresh request details when other users take actions
   * 
   * Listens for:
   * - 'request:updated' - Any action that changes the request (approve, reject, pause, resume, skip, etc.)
   * 
   * Behavior:
   * - Silently refreshes data in background
   * - Doesn't interrupt user actions
   * - Updates all tabs with latest data
   */
  useEffect(() => {
    if (!requestIdentifier || !apiRequest) return;

    const socket = getSocket();
    if (!socket) {
      return;
    }

    /**
     * Handler: Request updated by another user
     * Silently refresh to show latest changes
     */
    const handleRequestUpdated = (data: any) => {
      // Verify this update is for the current request
      if (data?.requestId === apiRequest.requestId || data?.requestNumber === requestIdentifier) {
        // Silent refresh - no loading state, no user interruption
        refreshDetails();
      }
    };

    // Register listener
    socket.on('request:updated', handleRequestUpdated);

    // Cleanup on unmount
    return () => {
      socket.off('request:updated', handleRequestUpdated);
    };
  }, [requestIdentifier, apiRequest, refreshDetails]);

  return {
    request,
    apiRequest,
    loading,
    refreshing,
    refreshDetails,
    currentApprovalLevel,
    isSpectator,
    isInitiator,
    existingParticipants,
    accessDenied
  };
}

