/**
 * User All Requests Page - For Regular Users
 * 
 * OPTIMIZED: Uses backend pagination (10 records per page) and backend stats API
 * Shows requests where the user is EITHER:
 * - The initiator (created by the user), OR
 * - A participant (approver/spectator)
 */

import { useEffect, useState, useCallback, useMemo, useRef } from 'react';
import { Pagination } from '@/components/common/Pagination';
import dashboardService from '@/services/dashboard.service';
import type { DateRange } from '@/services/dashboard.service';
import userApi from '@/services/userApi';

// Components
import { RequestsHeader } from './components/RequestsHeader';
import { RequestsStats } from './components/RequestsStats';
import { RequestsList } from './components/RequestsList';

// Hooks
import { useRequestsFilters } from './hooks/useRequestsFilters';
import { useUserSearch } from './hooks/useUserSearch';

// Utils
import { transformRequests } from './utils/requestTransformers';
import { exportRequestsToCSV } from './utils/csvExports';
import { getUserFilterType } from '@/utils/userFilterUtils';
import { getUserAllRequestsFilters } from '@/flows';
import { TokenManager } from '@/utils/tokenManager';

// Services
import { fetchUserParticipantRequestsData, fetchAllRequestsForExport } from './services/userRequestsService';

// Types
import type { RequestsProps, BackendStats } from './types/requests.types';

export function UserAllRequests({ onViewRequest }: RequestsProps) {
  // Filters hook
  const filters = useRequestsFilters();

  // Get user filter type and corresponding filter component (plug-and-play pattern)
  // Determine once at the beginning - no need to check repeatedly
  const userFilterType = useMemo(() => {
    try {
      const userData = TokenManager.getUserData();
      return getUserFilterType(userData);
    } catch (error) {
      console.error('[UserAllRequests] Error getting user filter type:', error);
      return 'STANDARD' as const;
    }
  }, []);

  // Get the appropriate filter component based on user type
  const UserAllRequestsFiltersComponent = useMemo(() => {
    return getUserAllRequestsFilters(userFilterType);
  }, [userFilterType]);

  // Determine once - use this throughout instead of checking repeatedly
  const isDealer = userFilterType === 'DEALER';
  
  // Helper to get filters for API - excludes dealer-restricted filters
  // Since we know user type initially, this helper uses that knowledge
  const getFiltersForApi = useCallback(() => {
    const filterOptions = filters.getFilters();
    if (isDealer) {
      // For dealers, exclude priority, templateType, department, and slaCompliance
      const { priority, templateType, department, slaCompliance, ...dealerFilters } = filterOptions;
      return dealerFilters;
    }
    return filterOptions;
  }, [filters, isDealer]);
  
  // Helper to calculate active filters count based on user type
  const calculateActiveFiltersCount = useCallback(() => {
    if (isDealer) {
      // For dealers: only count search, status, initiator, approver, and date filters
      return !!(
        filters.searchTerm ||
        filters.statusFilter !== 'all' ||
        filters.initiatorFilter !== 'all' ||
        filters.approverFilter !== 'all' ||
        filters.dateRange !== 'all' ||
        filters.customStartDate ||
        filters.customEndDate
      );
    }
    // For standard users: count all filters (use existing hasActiveFilters)
    return filters.hasActiveFilters;
  }, [isDealer, filters]);

  // State
  const [apiRequests, setApiRequests] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [exporting, setExporting] = useState(false);
  const [backendStats, setBackendStats] = useState<BackendStats | null>(null); // Stats from backend API
  const [departments, setDepartments] = useState<string[]>([]);
  const [loadingDepartments, setLoadingDepartments] = useState(false);
  const [allUsers, setAllUsers] = useState<Array<{ userId: string; email: string; displayName?: string }>>([]);

  // Pagination (currentPage now in Redux)
  const [totalPages, setTotalPages] = useState(1);
  const [totalRecords, setTotalRecords] = useState(0);
  const [itemsPerPage] = useState(10);

  // User search hooks
  const initiatorSearch = useUserSearch({
    allUsers,
    filterValue: filters.initiatorFilter,
    onFilterChange: filters.setInitiatorFilter
  });

  const approverSearch = useUserSearch({
    allUsers,
    filterValue: filters.approverFilter,
    onFilterChange: filters.setApproverFilter
  });

  // Fetch backend stats using dashboard API
  // OPTIMIZED: Uses backend stats API instead of fetching 100 records
  // Stats reflect all filters EXCEPT status - total stays stable when only status changes
  const fetchBackendStats = useCallback(async (
    statsDateRange?: DateRange, 
    statsStartDate?: Date, 
    statsEndDate?: Date,
    filtersWithoutStatus?: { 
      priority?: string; 
      templateType?: string;
      department?: string; 
      initiator?: string; 
      approver?: string; 
      approverType?: 'current' | 'any'; 
      search?: string;
      slaCompliance?: string;
    }
  ) => {
    try {
      // Use dashboard stats API with viewAsUser=true for user-level stats
      const stats = await dashboardService.getRequestStats(
        statsDateRange,
        statsStartDate ? statsStartDate.toISOString() : undefined,
        statsEndDate ? statsEndDate.toISOString() : undefined,
        undefined, // status - stats should show all statuses
        filtersWithoutStatus?.priority,
        filtersWithoutStatus?.templateType,
        filtersWithoutStatus?.department,
        filtersWithoutStatus?.initiator,
        filtersWithoutStatus?.approver,
        filtersWithoutStatus?.approverType,
        filtersWithoutStatus?.search,
        filtersWithoutStatus?.slaCompliance,
        true // viewAsUser: always true for user-level
      );

      setBackendStats({
        total: stats.totalRequests || 0,
        pending: stats.openRequests || 0,
        paused: stats.pausedRequests || 0,
        approved: stats.approvedRequests || 0,
        rejected: stats.rejectedRequests || 0,
        draft: stats.draftRequests || 0,
        closed: stats.closedRequests || 0
      });
    } catch (error) {
      console.error('Failed to fetch backend stats:', error);
      // Keep previous stats on error
    }
  }, []);

  // Fetch departments
  const fetchDepartments = useCallback(async () => {
    try {
      setLoadingDepartments(true);
      const depts = await dashboardService.getDepartments();
      setDepartments(depts);
    } catch (error) {
      // Leave departments empty on error
    } finally {
      setLoadingDepartments(false);
    }
  }, []);

  // Fetch users
  const fetchUsers = useCallback(async () => {
    try {
      const usersData = await userApi.getAllUsers();
      const usersList = usersData.map((user: any) => ({
        userId: user.userId,
        email: user.email,
        displayName: user.displayName || user.email
      }));
      setAllUsers(usersList);
    } catch (error) {
      console.error('Failed to fetch users:', error);
    }
  }, []);

  // Use refs to store stable callbacks to prevent infinite loops
  const filtersRef = useRef(filters);
  const fetchBackendStatsRef = useRef(fetchBackendStats);
  const getFiltersForApiRef = useRef(getFiltersForApi);
  
  // Update refs on each render
  useEffect(() => {
    filtersRef.current = filters;
    fetchBackendStatsRef.current = fetchBackendStats;
    getFiltersForApiRef.current = getFiltersForApi;
  }, [filters, fetchBackendStats, getFiltersForApi]);

  // Fetch requests - OPTIMIZED: Only fetches 10 records per page
  const fetchRequests = useCallback(async (page: number = 1) => {
    try {
      if (page === 1) {
        setLoading(true);
        setApiRequests([]);
      }

      const filterOptions = getFiltersForApiRef.current();
      const result = await fetchUserParticipantRequestsData({
        page,
        itemsPerPage,
        filters: filterOptions
      });

      setApiRequests(result.data); // Paginated data (10 records)

      // Update pagination
      filters.setCurrentPage(result.pagination.page);
      setTotalPages(result.pagination.totalPages);
      setTotalRecords(result.pagination.total);
    } catch (error) {
      setApiRequests([]);
    } finally {
      setLoading(false);
    }
  }, [itemsPerPage, filters]);

  // Export to CSV
  const handleExportToCSV = useCallback(async () => {
    try {
      setExporting(true);
      const exportFilters = getFiltersForApi();
      const allData = await fetchAllRequestsForExport(exportFilters);
      await exportRequestsToCSV(allData, exportFilters);
    } catch (error: any) {
      console.error('Failed to export requests:', error);
      alert('Failed to export requests. Please try again.');
    } finally {
      setExporting(false);
    }
  }, [getFiltersForApi]);

  // Initial fetch
  useEffect(() => {
    fetchDepartments();
    fetchUsers();
  }, [fetchDepartments, fetchUsers]);

  // Fetch backend stats when filters change (except status filter)
  // OPTIMIZED: Uses backend stats API instead of fetching 100 records
  useEffect(() => {
    const timeoutId = setTimeout(() => {
      const filtersWithoutStatus: {
        priority?: string;
        templateType?: string;
        department?: string;
        initiator?: string;
        approver?: string;
        approverType?: 'current' | 'any';
        search?: string;
        slaCompliance?: string;
      } = {
        initiator: filters.initiatorFilter !== 'all' ? filters.initiatorFilter : undefined,
        approver: filters.approverFilter !== 'all' ? filters.approverFilter : undefined,
        approverType: filters.approverFilter !== 'all' ? filters.approverFilterType : undefined,
        search: filters.searchTerm || undefined,
      };
      
      // Only include priority, templateType, department, and slaCompliance if user is not a dealer
      if (!isDealer) {
        if (filters.priorityFilter !== 'all') filtersWithoutStatus.priority = filters.priorityFilter;
        if (filters.templateTypeFilter !== 'all') filtersWithoutStatus.templateType = filters.templateTypeFilter;
        if (filters.departmentFilter !== 'all') filtersWithoutStatus.department = filters.departmentFilter;
        if (filters.slaComplianceFilter !== 'all') filtersWithoutStatus.slaCompliance = filters.slaComplianceFilter;
      }
      
      // Use 'all' if dateRange is 'all', otherwise use the selected dateRange or default to 'month'
      const statsDateRange = filters.dateRange === 'all' ? 'all' : (filters.dateRange || 'month');
      
      fetchBackendStatsRef.current(
        statsDateRange, 
        filters.customStartDate, 
        filters.customEndDate,
        filtersWithoutStatus
      );
    }, filters.searchTerm ? 500 : 0);

    return () => clearTimeout(timeoutId);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    filters.searchTerm,
    filters.priorityFilter,
    filters.slaComplianceFilter,
    filters.departmentFilter,
    filters.initiatorFilter,
    filters.approverFilter,
    filters.approverFilterType,
    filters.dateRange,
    filters.customStartDate,
    filters.customEndDate,
    filters.templateTypeFilter,
    isDealer
    // Note: statusFilter is NOT in dependencies - stats don't change when only status changes
  ]);

  // Track previous filter values to detect changes
  const prevFiltersRef = useRef({
    searchTerm: filters.searchTerm,
    statusFilter: filters.statusFilter,
    priorityFilter: filters.priorityFilter,
    templateTypeFilter: filters.templateTypeFilter,
    slaComplianceFilter: filters.slaComplianceFilter,
    departmentFilter: filters.departmentFilter,
    initiatorFilter: filters.initiatorFilter,
    approverFilter: filters.approverFilter,
    approverFilterType: filters.approverFilterType,
    dateRange: filters.dateRange,
    customStartDate: filters.customStartDate,
    customEndDate: filters.customEndDate,
  });
  const hasInitialFetchRun = useRef(false);
  
  // Initial fetch on mount - use stored page from Redux
  useEffect(() => {
    const storedPage = filters.currentPage || 1;
    fetchRequests(storedPage);
    hasInitialFetchRun.current = true;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []); // Only on mount
  
  // Fetch when filters change
  useEffect(() => {
    if (!hasInitialFetchRun.current) return;
    
    const prev = prevFiltersRef.current;
    const hasChanged = 
      prev.searchTerm !== filters.searchTerm ||
      prev.statusFilter !== filters.statusFilter ||
      prev.priorityFilter !== filters.priorityFilter ||
      prev.templateTypeFilter !== filters.templateTypeFilter ||
      prev.slaComplianceFilter !== filters.slaComplianceFilter ||
      prev.departmentFilter !== filters.departmentFilter ||
      prev.initiatorFilter !== filters.initiatorFilter ||
      prev.approverFilter !== filters.approverFilter ||
      prev.approverFilterType !== filters.approverFilterType ||
      prev.dateRange !== filters.dateRange ||
      prev.customStartDate !== filters.customStartDate ||
      prev.customEndDate !== filters.customEndDate;
    
    if (!hasChanged) return;
    
    const timeoutId = setTimeout(() => {
      filters.setCurrentPage(1);
      fetchRequests(1);
      
      prevFiltersRef.current = {
        searchTerm: filters.searchTerm,
        statusFilter: filters.statusFilter,
        priorityFilter: filters.priorityFilter,
        templateTypeFilter: filters.templateTypeFilter,
        slaComplianceFilter: filters.slaComplianceFilter,
        departmentFilter: filters.departmentFilter,
        initiatorFilter: filters.initiatorFilter,
        approverFilter: filters.approverFilter,
        approverFilterType: filters.approverFilterType,
        dateRange: filters.dateRange,
        customStartDate: filters.customStartDate,
        customEndDate: filters.customEndDate,
      };
    }, filters.searchTerm !== prev.searchTerm ? 500 : 0);

    return () => clearTimeout(timeoutId);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    filters.searchTerm,
    filters.statusFilter,
    filters.priorityFilter,
    filters.templateTypeFilter,
    filters.slaComplianceFilter,
    filters.departmentFilter,
    filters.initiatorFilter,
    filters.approverFilter,
    filters.approverFilterType,
    filters.dateRange,
    filters.customStartDate,
    filters.customEndDate
  ]);

  // Page change handler
  const handlePageChange = useCallback((newPage: number) => {
    if (newPage >= 1 && newPage <= totalPages) {
      filters.setCurrentPage(newPage);
      fetchRequests(newPage);
    }
  }, [totalPages, fetchRequests, filters]);

  // Transform requests
  const convertedRequests = useMemo(() => transformRequests(apiRequests), [apiRequests]);
  
  // Calculate stats - Use backend stats API (OPTIMIZED)
  const stats = useMemo(() => {
    // Use backend stats if available
    if (backendStats) {
      return {
        total: backendStats.total || 0,
        pending: backendStats.pending || 0,
        paused: backendStats.paused || 0,
        approved: backendStats.approved || 0,
        rejected: backendStats.rejected || 0,
        draft: backendStats.draft || 0,
        closed: backendStats.closed || 0
      };
    }
    
    // Fallback: calculate from current page (less accurate, but works during initial load)
      const pending = convertedRequests.filter((r: any) => {
        const status = (r.status || '').toString().toLowerCase();
        return status === 'pending' || status === 'in-progress';
      }).length;
    const paused = convertedRequests.filter((r: any) => {
      const status = (r.status || '').toString().toLowerCase();
      return status === 'paused';
    }).length;
      const approved = convertedRequests.filter((r: any) => {
        const status = (r.status || '').toString().toLowerCase();
        return status === 'approved';
      }).length;
      const rejected = convertedRequests.filter((r: any) => {
        const status = (r.status || '').toString().toLowerCase();
        return status === 'rejected';
      }).length;
      const closed = convertedRequests.filter((r: any) => {
        const status = (r.status || '').toString().toLowerCase();
        return status === 'closed';
      }).length;
      
      return {
      total: totalRecords > 0 ? totalRecords : convertedRequests.length,
        pending,
      paused,
        approved,
        rejected,
        draft: 0,
        closed
      };
  }, [backendStats, totalRecords, convertedRequests]);

  return (
    <div className="space-y-4 sm:space-y-6 max-w-7xl mx-auto" data-testid="user-all-requests-page">
      {/* Header */}
      <RequestsHeader
        isOrgLevel={false}
        isAdmin={false}
        loading={loading}
        exporting={exporting}
        onExport={handleExportToCSV}
      />

      {/* Stats */}
      <RequestsStats 
        stats={stats} 
        onStatusFilter={(status) => {
          filters.setStatusFilter(status);
        }}
      />

      {/* Filters - Plug-and-play pattern */}
      <UserAllRequestsFiltersComponent
        searchTerm={filters.searchTerm}
        statusFilter={filters.statusFilter}
        priorityFilter={filters.priorityFilter}
        templateTypeFilter={filters.templateTypeFilter}
        departmentFilter={filters.departmentFilter}
        slaComplianceFilter={filters.slaComplianceFilter}
        initiatorFilter={filters.initiatorFilter}
        approverFilter={filters.approverFilter}
        approverFilterType={filters.approverFilterType}
        dateRange={filters.dateRange}
        customStartDate={filters.customStartDate}
        customEndDate={filters.customEndDate}
        showCustomDatePicker={filters.showCustomDatePicker}
        departments={departments}
        loadingDepartments={loadingDepartments}
        initiatorSearch={initiatorSearch}
        approverSearch={approverSearch}
        onSearchChange={filters.setSearchTerm}
        onStatusChange={filters.setStatusFilter}
        onPriorityChange={filters.setPriorityFilter}
        onTemplateTypeChange={filters.setTemplateTypeFilter}
        onDepartmentChange={filters.setDepartmentFilter}
        onSlaComplianceChange={filters.setSlaComplianceFilter}
        onInitiatorChange={filters.setInitiatorFilter}
        onApproverChange={filters.setApproverFilter}
        onApproverTypeChange={filters.setApproverFilterType}
        onDateRangeChange={filters.handleDateRangeChange}
        onCustomStartDateChange={filters.setCustomStartDate}
        onCustomEndDateChange={filters.setCustomEndDate}
        onShowCustomDatePickerChange={filters.setShowCustomDatePicker}
        onApplyCustomDate={filters.handleApplyCustomDate}
        onClearFilters={filters.clearFilters}
        hasActiveFilters={calculateActiveFiltersCount()}
      />

      {/* Requests List */}
      <RequestsList
        requests={convertedRequests}
        loading={loading}
        hasActiveFilters={filters.hasActiveFilters}
        onViewRequest={onViewRequest}
      />

      {/* Pagination */}
      <Pagination
        currentPage={filters.currentPage || 1}
        totalPages={totalPages}
        totalRecords={totalRecords}
        itemsPerPage={itemsPerPage}
        onPageChange={handlePageChange}
        loading={loading}
        itemLabel="requests"
        testIdPrefix="requests-pagination"
      />
    </div>
  );
}

