"use client";

import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import {
  Box,
  Typography,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  Card,
  CardContent,
  Stack,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Paper,
  CircularProgress,
  Chip
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs';
import { fetchTruckScheduleDashboardClient, type TruckScheduleDashboardItem } from '@/app/api/do/client';
import { formatDepartureTime, arrayToDayjs } from '@/app/utils/formatUtil';

// Track completed items for hiding after 2 refresh cycles
interface CompletedTracker {
  key: string;
  refreshCount: number;
}

// Data stored per date for instant switching
interface DateData {
  today: TruckScheduleDashboardItem[];
  tomorrow: TruckScheduleDashboardItem[];
  dayAfterTomorrow: TruckScheduleDashboardItem[];
}

// Storage structure for persisting completed tracker state
interface PersistedTrackerState {
  completedTracker: {
    [dateOption: string]: { [key: string]: CompletedTracker };
  };
  refreshCount: {
    [dateOption: string]: number;
  };
}

const STORAGE_KEY = 'truckScheduleCompletedTracker';

const TruckScheduleDashboard: React.FC = () => {
  const { t } = useTranslation("dashboard");
  const [selectedStore, setSelectedStore] = useState<string>("");
  const [selectedDate, setSelectedDate] = useState<string>("today");
  // Store data for all three dates for instant switching
  const [allData, setAllData] = useState<DateData>({ today: [], tomorrow: [], dayAfterTomorrow: [] });
  const [loading, setLoading] = useState<boolean>(true);
  // Initialize as null to avoid SSR/client hydration mismatch
  const [currentTime, setCurrentTime] = useState<dayjs.Dayjs | null>(null);
  const [isClient, setIsClient] = useState<boolean>(false);
  // Track when data was last refreshed (not current time)
  const [lastDataRefreshTime, setLastDataRefreshTime] = useState<dayjs.Dayjs | null>(null);
  // Track completed items per date
  const completedTrackerRef = useRef<Map<string, Map<string, CompletedTracker>>>(new Map([
    ['today', new Map()],
    ['tomorrow', new Map()],
    ['dayAfterTomorrow', new Map()]
  ]));
  const refreshCountRef = useRef<Map<string, number>>(new Map([
    ['today', 0],
    ['tomorrow', 0],
    ['dayAfterTomorrow', 0]
  ]));
    const [now, setNow] = useState(dayjs());
  // Save completed tracker state to sessionStorage
  const saveCompletedTrackerToStorage = useCallback(() => {
    if (typeof window === 'undefined') return;
    
    try {
      const completedTrackerObj: { [dateOption: string]: { [key: string]: CompletedTracker } } = {};
      const refreshCountObj: { [dateOption: string]: number } = {};
      
      // Convert Maps to plain objects
      completedTrackerRef.current.forEach((tracker, dateOption) => {
        completedTrackerObj[dateOption] = Object.fromEntries(tracker);
      });
      
      refreshCountRef.current.forEach((count, dateOption) => {
        refreshCountObj[dateOption] = count;
      });
      
      const state: PersistedTrackerState = {
        completedTracker: completedTrackerObj,
        refreshCount: refreshCountObj
      };
      
      sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));
    } catch (error) {
      console.warn('Failed to save completed tracker to sessionStorage:', error);
    }
  }, []);

  // Load completed tracker state from sessionStorage
  const loadCompletedTrackerFromStorage = useCallback((): boolean => {
    if (typeof window === 'undefined') return false;
    
    try {
      const saved = sessionStorage.getItem(STORAGE_KEY);
      if (!saved) return false;
      
      const state: PersistedTrackerState = JSON.parse(saved);
      
      // Reconstruct Maps from plain objects
      const completedTrackerMap = new Map<string, Map<string, CompletedTracker>>();
      const refreshCountMap = new Map<string, number>();
      
      Object.entries(state.completedTracker).forEach(([dateOption, trackerObj]) => {
        completedTrackerMap.set(dateOption, new Map(Object.entries(trackerObj)));
      });
      
      Object.entries(state.refreshCount).forEach(([dateOption, count]) => {
        refreshCountMap.set(dateOption, count);
      });
      
      completedTrackerRef.current = completedTrackerMap;
      refreshCountRef.current = refreshCountMap;
      
      return true;
    } catch (error) {
      console.warn('Failed to load completed tracker from sessionStorage:', error);
      return false;
    }
  }, []);

  // Get date label for display (e.g., "2026-01-17")
  const getDateLabel = (offset: number): string => {
    return dayjs().add(offset, 'day').format('YYYY-MM-DD');
  };

  // Get day offset based on date option
  const getDateOffset = (dateOption: string): number => {
    if (dateOption === "today") return 0;
    if (dateOption === "tomorrow") return 1;
    if (dateOption === "dayAfterTomorrow") return 2;
    return 0;
  };

  // Convert date option to YYYY-MM-DD format for API
  const getDateParam = (dateOption: string): string => {
    const offset = getDateOffset(dateOption);
    return dayjs().add(offset, 'day').format('YYYY-MM-DD');
  };
  
  // Set client flag and time on mount, load persisted state
  useEffect(() => {
    setIsClient(true);
    setCurrentTime(dayjs());
    // Load persisted completed tracker state from sessionStorage
    loadCompletedTrackerFromStorage();
  }, [loadCompletedTrackerFromStorage]);

  // Format time from array or string to HH:mm
  const formatTime = (timeData: string | number[] | null): string => {
    if (!timeData) return '-';
    
    if (Array.isArray(timeData)) {
      if (timeData.length >= 2) {
        const hour = timeData[0] || 0;
        const minute = timeData[1] || 0;
        return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
      }
      return '-';
    }
    
    if (typeof timeData === 'string') {
      const parts = timeData.split(':');
      if (parts.length >= 2) {
        const hour = parseInt(parts[0], 10);
        const minute = parseInt(parts[1], 10);
        return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
      }
    }
    
    return '-';
  };

  // Format datetime from array or string
  const formatDateTime = (dateTimeData: string | number[] | null): string => {
    if (!dateTimeData) return '-';
    
    if (Array.isArray(dateTimeData)) {
      return arrayToDayjs(dateTimeData, true).format('HH:mm');
    }
    
    const parsed = dayjs(dateTimeData);
    if (parsed.isValid()) {
      return parsed.format('HH:mm');
    }
    
    return '-';
  };

  // Compare a timestamp against the selected date (today/tomorrow/...) and return a short label.
  // Used to avoid confusion when picking crosses midnight.
  const relativeDayLabel = useCallback(
    (dateTimeData: string | number[] | null, dateOption: string): string | null => {
      if (!dateTimeData) return null;
      const dateOffset = getDateOffset(dateOption);
      const baseDate = dayjs().startOf('day').add(dateOffset, 'day');

      let dt: dayjs.Dayjs;
      if (Array.isArray(dateTimeData)) {
        dt = arrayToDayjs(dateTimeData, true);
      } else {
        dt = dayjs(dateTimeData);
      }
      if (!dt.isValid()) return null;

      const diffDays = dt.startOf('day').diff(baseDate, 'day');
      if (diffDays === 0) return null;
      if (diffDays === -1) return '昨日';
      if (diffDays === 1) return '明日';
      if (diffDays <= -2) return `${Math.abs(diffDays)}日前`;
      return `${diffDays}日後`;
    },
    [],
  );

  const getDepartureEtdDayjs = useCallback(
    (departureTime: string | number[] | null, dateOption: string): dayjs.Dayjs | null => {
      if (!departureTime) return null;
      const dateOffset = getDateOffset(dateOption);
      const baseDate = dayjs().startOf('day').add(dateOffset, 'day');

      let hour: number;
      let minute: number;

      if (Array.isArray(departureTime)) {
        if (departureTime.length < 2) return null;
        hour = departureTime[0] || 0;
        minute = departureTime[1] || 0;
      } else if (typeof departureTime === 'string') {
        const parts = departureTime.split(':');
        if (parts.length < 2) return null;
        hour = parseInt(parts[0], 10);
        minute = parseInt(parts[1], 10);
      } else {
        return null;
      }

      return baseDate.hour(hour).minute(minute).second(0);
    },
    [],
  );

  const getLastEndDayjsOrNull = useCallback((lastTicketEndTime: string | number[] | null): dayjs.Dayjs | null => {
    if (!lastTicketEndTime) return null;
    if (Array.isArray(lastTicketEndTime)) {
      return arrayToDayjs(lastTicketEndTime, true);
    }
    const d = dayjs(lastTicketEndTime);
    return d.isValid() ? d : null;
  }, []);

  const getDiffMinutesForRemaining = useCallback(
    (item: TruckScheduleDashboardItem, dateOption: string): number | null => {
      if (!currentTime) return null;
      const etd = getDepartureEtdDayjs(item.truckDepartureTime, dateOption);
      if (!etd) return null;

      const allDone =
        item.numberOfTicketsReleased > 0 && item.numberOfTicketsCompleted >= item.numberOfTicketsReleased;
      if (allDone) {
        const lastEnd = getLastEndDayjsOrNull(item.lastTicketEndTime);
        if (!lastEnd) return null;
        return etd.diff(lastEnd, 'minute');
      }

      return etd.diff(currentTime, 'minute');
    },
    [currentTime, getDepartureEtdDayjs, getLastEndDayjsOrNull],
  );

  // Calculate time remaining for truck departure
  const calculateTimeRemaining = useCallback((item: TruckScheduleDashboardItem, dateOption: string): string => {
    const diffMinutes = getDiffMinutesForRemaining(item, dateOption);
    if (diffMinutes === null) return '-';
    
    if (diffMinutes < 0) {
      // Past departure time
      const absDiff = Math.abs(diffMinutes);
      const hours = Math.floor(absDiff / 60);
      const minutes = absDiff % 60;
      return `-${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
    } else {
      const hours = Math.floor(diffMinutes / 60);
      const minutes = diffMinutes % 60;
      return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
    }
  }, [getDiffMinutesForRemaining]);

  // Generate unique key for tracking completed items
  const getItemKey = (item: TruckScheduleDashboardItem): string => {
    return `${item.storeId}-${item.truckLanceCode}-${item.truckDepartureTime}`;
  };

  // Process data for a specific date option with completed tracker logic
  const processDataForDate = useCallback((result: TruckScheduleDashboardItem[], dateOption: string): TruckScheduleDashboardItem[] => {
    const tracker = completedTrackerRef.current.get(dateOption) || new Map();
    const currentRefresh = (refreshCountRef.current.get(dateOption) || 0) + 1;
    refreshCountRef.current.set(dateOption, currentRefresh);
    
    result.forEach(item => {
      const key = getItemKey(item);
      // If all tickets are completed, track it
      if (item.numberOfPickTickets > 0 && item.numberOfTicketsCompleted >= item.numberOfPickTickets) {
        const existing = tracker.get(key);
        if (!existing) {
          tracker.set(key, { key, refreshCount: currentRefresh });
        }
      } else {
        // Remove from tracker if no longer completed
        tracker.delete(key);
      }
    });
    
    completedTrackerRef.current.set(dateOption, tracker);
    
    // Save to sessionStorage after updating tracker
    saveCompletedTrackerToStorage();
    
    // Filter out items that have been completed for 2+ refresh cycles
    return result.filter(item => {
      const key = getItemKey(item);
      const itemTracker = tracker.get(key);
      if (itemTracker) {
        // Hide if completed for 2 or more refresh cycles
        if (currentRefresh - itemTracker.refreshCount >= 2) {
          return false;
        }
      }
      return true;
    });
  }, [saveCompletedTrackerToStorage]);

  // Load data for all three dates in parallel for instant switching
  const loadData = useCallback(async (isInitialLoad: boolean = false) => {
    // Only show loading spinner on initial load, not during refresh
    if (isInitialLoad) {
      setLoading(true);
    }
    try {
      const dateOptions = ['today', 'tomorrow', 'dayAfterTomorrow'] as const;
      const dateParams = dateOptions.map(opt => getDateParam(opt));
      
      // Fetch all three dates in parallel
      const [todayResult, tomorrowResult, dayAfterResult] = await Promise.all([
        fetchTruckScheduleDashboardClient(dateParams[0]),
        fetchTruckScheduleDashboardClient(dateParams[1]),
        fetchTruckScheduleDashboardClient(dateParams[2])
      ]);
      
      // Process each date's data with completed tracker logic
      setAllData({
        today: processDataForDate(todayResult, 'today'),
        tomorrow: processDataForDate(tomorrowResult, 'tomorrow'),
        dayAfterTomorrow: processDataForDate(dayAfterResult, 'dayAfterTomorrow')
      });
      
      // Update last data refresh time only when data is successfully loaded
      setLastDataRefreshTime(dayjs());
    } catch (error) {
      console.error('Error fetching truck schedule dashboard:', error);
    } finally {
      if (isInitialLoad) {
        setLoading(false);
      }
    }
  }, [processDataForDate]);

  useEffect(() => {
    const timer = setInterval(() => setNow(dayjs()), 60 * 1000);
    return () => clearInterval(timer);
  }, []);

  // Initial load and auto-refresh every 5 minutes
  useEffect(() => {
    loadData(true); // Initial load - show spinner
    
    const refreshInterval = setInterval(() => {
      loadData(false); // Refresh - don't show spinner, keep existing data visible
    }, 5 * 60 * 1000); // 5 minutes
    
    return () => clearInterval(refreshInterval);
  }, [loadData]);

  // Update current time every 1 minute for time remaining calculation
  useEffect(() => {
    if (!isClient) return;
    
    const timeInterval = setInterval(() => {
      setCurrentTime(dayjs());
    }, 60 * 1000); // 1 minute
    
    return () => clearInterval(timeInterval);
  }, [isClient]);

  // Get data for selected date, then filter by store - both filters are instant
  const filteredData = useMemo(() => {
    // First get the data for the selected date
    const dateData = allData[selectedDate as keyof DateData] || [];
    // Then filter by store if selected
    if (!selectedStore) return dateData;
    return dateData.filter(item => item.storeId === selectedStore);
  }, [allData, selectedDate, selectedStore]);

  // Get chip color based on time remaining
  const getTimeChipColor = (item: TruckScheduleDashboardItem, dateOption: string): "success" | "warning" | "error" | "default" => {
    const diffMinutes = getDiffMinutesForRemaining(item, dateOption);
    if (diffMinutes === null) return "default";
    if (diffMinutes < 0) return "error";
    if (diffMinutes < 30) return "warning";
    return "success";
  };

  return (
    <Card sx={{ mb: 2 }}>
      <CardContent>
        {/* Title */}
        <Typography variant="h5" sx={{ fontWeight: 600, mb: 2 }}>
          {t("Truck Schedule Dashboard")}
        </Typography>

        {/* Filter */}
        <Stack direction="row" spacing={2} sx={{ mb: 3 }}>
          <FormControl sx={{ minWidth: 150 }} size="small">
            <InputLabel id="store-select-label" shrink={true}>
              {t("Store ID")}
            </InputLabel>
            <Select
              labelId="store-select-label"
              id="store-select"
              value={selectedStore}
              label={t("Store ID")}
              onChange={(e) => setSelectedStore(e.target.value)}
              displayEmpty
            >
              <MenuItem value="">{t("All Stores")}</MenuItem>
              <MenuItem value="2/F">2/F</MenuItem>
              <MenuItem value="4/F">4/F</MenuItem>
            </Select>
          </FormControl>

          <FormControl sx={{ minWidth: 200 }} size="small">
            <InputLabel id="date-select-label" shrink={true}>
              {t("Select Date")}
            </InputLabel>
            <Select
              labelId="date-select-label"
              id="date-select"
              value={selectedDate}
              label={t("Select Date")}
              onChange={(e) => setSelectedDate(e.target.value)}
            >
              <MenuItem value="today">{t("Today")} ({getDateLabel(0)})</MenuItem>
              <MenuItem value="tomorrow">{t("Tomorrow")} ({getDateLabel(1)})</MenuItem>
              <MenuItem value="dayAfterTomorrow">{t("Day After Tomorrow")} ({getDateLabel(2)})</MenuItem>
            </Select>
          </FormControl>

        <Box sx={{ flexGrow: 1 }} />
        <Stack direction="row" spacing={2} sx={{ alignSelf: 'center' }}>
          <Typography variant="body2" sx={{ color: 'text.secondary' }} suppressHydrationWarning>
            {t("Now")}: {now.format('HH:mm')}
          </Typography>
          <Typography variant="body2" sx={{ color: 'text.secondary' }}>
            {t("Auto-refresh every 5 minutes")} | {t("Last updated")}: {lastDataRefreshTime ? lastDataRefreshTime.format('HH:mm:ss') : '--:--:--'}
          </Typography>
        </Stack>
        </Stack>

        {/* Table */}
        <Box sx={{ mt: 2 }}>
          {loading ? (
            <Box sx={{ display: 'flex', justifyContent: 'center', p: 3 }}>
              <CircularProgress />
            </Box>
          ) : (
            <TableContainer component={Paper} sx={{ maxHeight: 440, overflow: 'auto' }}>
              <Table size="small" sx={{ minWidth: 1200 }}>
                <TableHead>
                  <TableRow sx={{ backgroundColor: 'grey.100', position: 'sticky', top: 0, zIndex: 1 }}>
                    <TableCell sx={{ fontWeight: 600 }}>{t("Store ID")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>{t("Truck Schedule")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>{t("Time Remaining")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }} align="right">{t("No. of Shops")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }} align="right">{t("Tickets Released")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }} align="right">{t("Tickets Completed")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }} align="right">{t("Total Items")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>{t("First Ticket Start")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }}>{t("Last Ticket End")}</TableCell>
                    <TableCell sx={{ fontWeight: 600 }} align="right">{t("Pick Time (min)")}</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {filteredData.length === 0 ? (
                    <TableRow>
                      <TableCell colSpan={10} align="center">
                        <Typography variant="body2" color="text.secondary">
                          {t("No truck schedules available")} ({getDateParam(selectedDate)})
                        </Typography>
                      </TableCell>
                    </TableRow>
                  ) : (
                    filteredData.map((row, index) => {
                      const timeRemaining = calculateTimeRemaining(row, selectedDate);
                      const chipColor = getTimeChipColor(row, selectedDate);
                      const startRel = relativeDayLabel(row.firstTicketStartTime, selectedDate);
                      const endRel = relativeDayLabel(row.lastTicketEndTime, selectedDate);
                      
                      return (
                        <TableRow 
                          key={`${row.storeId}-${row.truckLanceCode}-${index}`}
                          sx={{ 
                            '&:hover': { backgroundColor: 'grey.50' },
                            backgroundColor: row.numberOfPickTickets > 0 && row.numberOfTicketsCompleted >= row.numberOfPickTickets 
                              ? 'rgba(76, 175, 80, 0.15)' 
                              : 'inherit'
                          }}
                        >
                          <TableCell>
                            <Chip 
                              label={row.storeId || '-'} 
                              size="small" 
                              color={row.storeId === '2/F' ? 'primary' : 'secondary'}
                            />
                          </TableCell>
                          <TableCell>
                            <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
                              <Typography variant="body2" sx={{ fontWeight: 500 }}>
                                {row.truckLanceCode || '-'}
                              </Typography>
                              <Typography variant="caption" color="text.secondary">
                                ETD: {formatTime(row.truckDepartureTime)}
                              </Typography>
                            </Box>
                          </TableCell>
                          <TableCell>
                            <Chip 
                              label={timeRemaining}
                              size="small"
                              color={chipColor}
                              sx={{ fontWeight: 600 }}
                            />
                          </TableCell>
                          <TableCell align="right">
                            <Typography variant="body2">
                              {row.numberOfShopsToServe} [{row.numberOfPickTickets}]
                            </Typography>
                          </TableCell>
                          <TableCell align="right">
                            <Chip 
                              label={row.numberOfTicketsReleased}
                              size="small"
                              color={row.numberOfTicketsReleased > 0 ? 'info' : 'default'}
                            />
                          </TableCell>
                          <TableCell align="right">
                            <Chip 
                              label={row.numberOfTicketsCompleted}
                              size="small"
                              color={row.numberOfTicketsCompleted > 0 ? 'success' : 'default'}
                            />
                          </TableCell>
                          <TableCell align="right">
                            <Typography variant="body2" sx={{ fontWeight: 500 }}>
                              {row.totalItemsToPick}
                            </Typography>
                          </TableCell>
                          <TableCell>
                            <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
                              <Typography variant="body2">{formatDateTime(row.firstTicketStartTime)}</Typography>
                              {startRel && (
                                <Chip size="small" variant="outlined" color="warning" label={startRel} />
                              )}
                            </Box>
                          </TableCell>
                          <TableCell>
                            <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
                              <Typography variant="body2">{formatDateTime(row.lastTicketEndTime)}</Typography>
                              {endRel && (
                                <Chip size="small" variant="outlined" color="warning" label={endRel} />
                              )}
                            </Box>
                          </TableCell>
                          <TableCell align="right">
                            <Typography 
                              variant="body2" 
                              sx={{ 
                                fontWeight: 500,
                                color: row.pickTimeTakenMinutes !== null ? 'text.primary' : 'text.secondary'
                              }}
                            >
                              {row.pickTimeTakenMinutes !== null ? row.pickTimeTakenMinutes : '-'}
                            </Typography>
                          </TableCell>
                        </TableRow>
                      );
                    })
                  )}
                </TableBody>
              </Table>
            </TableContainer>
          )}
        </Box>
      </CardContent>
    </Card>
  );
};

export default TruckScheduleDashboard;
