/**
 * Jobs List Screen
 *
 * Displays jobs in a timeline view with day/week toggle.
 * Supports drag-and-drop rescheduling and resize if user has permission.
 */

import { useCallback, useState, useRef, useMemo } from 'react';
import {
  View,
  Text,
  ScrollView,
  TouchableOpacity,
  StyleSheet,
  RefreshControl,
  ActivityIndicator,
  Alert,
  Dimensions,
} from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useRouter } from 'expo-router';
import { useQueryClient } from '@tanstack/react-query';
import { Ionicons } from '@expo/vector-icons';
import { getJobColor, updateAppointmentTime } from '../../src/api/jobs';
import { useAuth } from '../../src/hooks/useAuth';
import { useJobs } from '../../src/hooks/useJobs';
import { DraggableJobBlock } from '../../src/components/DraggableJobBlock';
import type { JobListItem, JobStatus } from '../../src/types';

const HOUR_HEIGHT = 60;
const SCREEN_WIDTH = Dimensions.get('window').width;
const DAY_COLUMN_WIDTH = (SCREEN_WIDTH - 50) / 7; // For week view
const DAY_VIEW_WIDTH = SCREEN_WIDTH - 70; // Width available for job blocks in day view

type ViewMode = 'day' | 'week';

// Lane layout calculation for overlapping appointments
interface JobWithLane extends JobListItem {
  laneIndex: number;
  totalLanes: number;
}

function calculateLaneLayout(jobs: JobListItem[]): JobWithLane[] {
  if (jobs.length === 0) return [];

  // Sort by start time
  const sortedJobs = [...jobs].sort((a, b) =>
    new Date(a.start_time).getTime() - new Date(b.start_time).getTime()
  );

  // Find overlapping groups and assign lanes
  const result: JobWithLane[] = [];
  const laneEndTimes: number[] = [];

  // First pass: assign lane indices
  const jobsWithLanes = sortedJobs.map((job) => {
    const startTime = new Date(job.start_time).getTime();
    const endTime = new Date(job.end_time).getTime();

    // Find the first available lane
    let laneIndex = 0;
    while (laneIndex < laneEndTimes.length && laneEndTimes[laneIndex] > startTime) {
      laneIndex++;
    }

    // Assign end time to this lane
    laneEndTimes[laneIndex] = endTime;

    return { ...job, laneIndex, totalLanes: 1 };
  });

  // Second pass: find overlapping groups and set totalLanes
  // Group overlapping jobs together
  const groups: JobWithLane[][] = [];
  let currentGroup: JobWithLane[] = [];
  let groupEndTime = 0;

  jobsWithLanes.forEach((job) => {
    const startTime = new Date(job.start_time).getTime();
    const endTime = new Date(job.end_time).getTime();

    if (currentGroup.length === 0 || startTime < groupEndTime) {
      // Job overlaps with current group
      currentGroup.push(job);
      groupEndTime = Math.max(groupEndTime, endTime);
    } else {
      // Start a new group
      if (currentGroup.length > 0) {
        groups.push(currentGroup);
      }
      currentGroup = [job];
      groupEndTime = endTime;
    }
  });

  if (currentGroup.length > 0) {
    groups.push(currentGroup);
  }

  // Set totalLanes for each job in its group
  groups.forEach((group) => {
    const maxLane = Math.max(...group.map(j => j.laneIndex)) + 1;
    group.forEach((job) => {
      job.totalLanes = maxLane;
      result.push(job);
    });
  });

  return result;
}

function formatTime(dateString: string): string {
  const date = new Date(dateString);
  return date.toLocaleTimeString('en-US', {
    hour: 'numeric',
    minute: '2-digit',
    hour12: true,
  });
}

function getHourLabel(hour: number): string {
  if (hour === 0) return '12 AM';
  if (hour === 12) return '12 PM';
  if (hour < 12) return `${hour} AM`;
  return `${hour - 12} PM`;
}

function isSameDay(date1: Date, date2: Date): boolean {
  // Compare using local date parts
  return (
    date1.getFullYear() === date2.getFullYear() &&
    date1.getMonth() === date2.getMonth() &&
    date1.getDate() === date2.getDate()
  );
}

function parseJobDate(dateString: string): Date {
  // Parse ISO date string and return a Date object
  return new Date(dateString);
}

function getWeekDays(baseDate: Date): Date[] {
  const days: Date[] = [];
  const startOfWeek = new Date(baseDate);
  startOfWeek.setDate(baseDate.getDate() - baseDate.getDay()); // Start on Sunday

  for (let i = 0; i < 7; i++) {
    const day = new Date(startOfWeek);
    day.setDate(startOfWeek.getDate() + i);
    days.push(day);
  }
  return days;
}

// Note: JobBlock functionality moved to DraggableJobBlock component
// which supports drag-and-drop rescheduling and resize

function TimelineGrid({ viewMode }: { viewMode: ViewMode }) {
  const hours = [];
  for (let hour = 0; hour < 24; hour++) {
    hours.push(hour);
  }

  return (
    <View style={styles.timelineGrid}>
      {hours.map((hour) => (
        <View key={hour} style={styles.hourRow}>
          <Text style={styles.hourLabel}>{getHourLabel(hour)}</Text>
          <View style={styles.hourLine} />
        </View>
      ))}
    </View>
  );
}

function WeekHeader({ weekDays, selectedDate }: { weekDays: Date[]; selectedDate: Date }) {
  const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
  const today = new Date();

  return (
    <View style={styles.weekHeader}>
      <View style={styles.weekHeaderSpacer} />
      {weekDays.map((day, index) => {
        const isToday = isSameDay(day, today);
        const isSelected = isSameDay(day, selectedDate);
        return (
          <View key={index} style={styles.weekDayHeader}>
            <Text style={[styles.weekDayName, isToday && styles.weekDayNameToday]}>
              {dayNames[index]}
            </Text>
            <View style={[
              styles.weekDayNumber,
              isToday && styles.weekDayNumberToday,
            ]}>
              <Text style={[
                styles.weekDayNumberText,
                isToday && styles.weekDayNumberTextToday,
              ]}>
                {day.getDate()}
              </Text>
            </View>
          </View>
        );
      })}
    </View>
  );
}

function CurrentTimeLine({ viewMode }: { viewMode: ViewMode }) {
  const now = new Date();
  const currentHour = now.getHours() + now.getMinutes() / 60;
  const top = currentHour * HOUR_HEIGHT;

  return (
    <View style={[styles.currentTimeLine, { top }]}>
      <View style={styles.currentTimeDot} />
      <View style={styles.currentTimeLineBar} />
    </View>
  );
}

export default function JobsScreen() {
  const insets = useSafeAreaInsets();
  const router = useRouter();
  const queryClient = useQueryClient();
  const { user, logout } = useAuth();
  const [refreshing, setRefreshing] = useState(false);
  const [viewMode, setViewMode] = useState<ViewMode>('day');
  const [selectedDate, setSelectedDate] = useState(new Date());
  const scrollRef = useRef<ScrollView>(null);

  // Check if user can edit schedule
  const canEditSchedule = user?.can_edit_schedule ?? false;

  const weekDays = useMemo(() => getWeekDays(selectedDate), [selectedDate]);

  // Calculate the date range to fetch based on view mode
  const jobsQueryParams = useMemo(() => {
    if (viewMode === 'day') {
      // For day view, fetch just that day
      const startOfDay = new Date(selectedDate);
      startOfDay.setHours(0, 0, 0, 0);
      const endOfDay = new Date(selectedDate);
      endOfDay.setHours(23, 59, 59, 999);

      return {
        startDate: startOfDay.toISOString(),
        endDate: endOfDay.toISOString(),
      };
    } else {
      // For week view, fetch the entire week
      const weekStart = new Date(weekDays[0]);
      weekStart.setHours(0, 0, 0, 0);
      const weekEnd = new Date(weekDays[6]);
      weekEnd.setHours(23, 59, 59, 999);

      return {
        startDate: weekStart.toISOString(),
        endDate: weekEnd.toISOString(),
      };
    }
  }, [selectedDate, viewMode, weekDays]);

  // Use the jobs hook with WebSocket integration for real-time updates
  const {
    data,
    isLoading,
    error,
    refresh,
    isConnected,
  } = useJobs(jobsQueryParams);

  const onRefresh = useCallback(async () => {
    setRefreshing(true);
    await refresh();
    setRefreshing(false);
  }, [refresh]);

  const handleJobPress = (jobId: number) => {
    router.push(`/(auth)/job/${jobId}`);
  };

  const handleLogout = () => {
    Alert.alert(
      'Logout',
      'Are you sure you want to logout?',
      [
        { text: 'Cancel', style: 'cancel' },
        {
          text: 'Logout',
          style: 'destructive',
          onPress: async () => {
            await logout();
            router.replace('/login');
          },
        },
      ]
    );
  };

  // Handle drag-and-drop time changes
  const handleTimeChange = useCallback(async (
    jobId: number,
    newStartTime: Date,
    newEndTime: Date
  ) => {
    try {
      await updateAppointmentTime(jobId, {
        start_time: newStartTime.toISOString(),
        end_time: newEndTime.toISOString(),
      });
      // Invalidate queries to refresh the data
      queryClient.invalidateQueries({ queryKey: ['jobs'] });
    } catch (error: any) {
      throw new Error(error.response?.data?.detail || 'Failed to update appointment');
    }
  }, [queryClient]);

  // Scroll to current time on mount
  const scrollToNow = useCallback(() => {
    const now = new Date();
    const currentHour = now.getHours();
    const scrollPosition = Math.max(0, (currentHour - 1) * HOUR_HEIGHT);
    scrollRef.current?.scrollTo({ y: scrollPosition, animated: false });
  }, []);

  // Filter jobs based on view mode
  const filteredJobs = useMemo(() => {
    const jobs = data?.jobs || [];
    if (viewMode === 'day') {
      return jobs.filter(job => isSameDay(new Date(job.start_time), selectedDate));
    }
    // Week view - return all jobs for the week
    const weekStart = weekDays[0];
    const weekEnd = new Date(weekDays[6]);
    weekEnd.setHours(23, 59, 59, 999);

    return jobs.filter(job => {
      const jobDate = new Date(job.start_time);
      return jobDate >= weekStart && jobDate <= weekEnd;
    });
  }, [data?.jobs, viewMode, selectedDate, weekDays]);

  // Calculate lane layout for day view (overlapping appointments)
  const dayJobsWithLanes = useMemo(() => {
    if (viewMode !== 'day') return [];
    return calculateLaneLayout(filteredJobs);
  }, [filteredJobs, viewMode]);

  // Group jobs by day for week view with lane layout
  const jobsByDay = useMemo(() => {
    if (viewMode !== 'week') return {};

    // First group raw jobs by day
    const tempGrouped: Record<number, JobListItem[]> = {};
    weekDays.forEach((_, index) => {
      tempGrouped[index] = [];
    });

    filteredJobs.forEach(job => {
      const jobDate = new Date(job.start_time);
      const dayIndex = weekDays.findIndex(day => isSameDay(day, jobDate));
      if (dayIndex !== -1) {
        tempGrouped[dayIndex].push(job);
      }
    });

    // Then calculate lane layout for each day
    const grouped: Record<number, JobWithLane[]> = {};
    Object.keys(tempGrouped).forEach(key => {
      const dayIndex = parseInt(key);
      grouped[dayIndex] = calculateLaneLayout(tempGrouped[dayIndex]);
    });

    return grouped;
  }, [filteredJobs, viewMode, weekDays]);

  if (isLoading && !refreshing) {
    return (
      <View style={[styles.centerContainer, { paddingTop: insets.top }]}>
        <ActivityIndicator size="large" color="#2563eb" />
        <Text style={styles.loadingText}>Loading jobs...</Text>
      </View>
    );
  }

  if (error) {
    return (
      <View style={[styles.centerContainer, { paddingTop: insets.top }]}>
        <Ionicons name="alert-circle-outline" size={48} color="#ef4444" />
        <Text style={styles.errorText}>Failed to load jobs</Text>
        <TouchableOpacity style={styles.retryButton} onPress={refresh}>
          <Text style={styles.retryButtonText}>Try Again</Text>
        </TouchableOpacity>
      </View>
    );
  }

  const today = selectedDate.toLocaleDateString('en-US', {
    weekday: 'long',
    month: 'long',
    day: 'numeric',
  });

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
    <View style={[styles.container, { paddingTop: insets.top }]}>
      <View style={styles.header}>
        <View>
          <Text style={styles.greeting}>Hello, {user?.name || 'there'}!</Text>
          <Text style={styles.dateText}>{today}</Text>
        </View>
        <TouchableOpacity onPress={handleLogout} style={styles.logoutButton}>
          <Ionicons name="log-out-outline" size={24} color="#fff" />
        </TouchableOpacity>
      </View>

      {/* View Mode Toggle */}
      {/* Date Navigation */}
      <View style={styles.dateNavContainer}>
        <TouchableOpacity
          style={styles.navButton}
          onPress={() => {
            const newDate = new Date(selectedDate);
            if (viewMode === 'day') {
              newDate.setDate(newDate.getDate() - 1);
            } else {
              newDate.setDate(newDate.getDate() - 7);
            }
            setSelectedDate(newDate);
          }}
        >
          <Ionicons name="chevron-back" size={24} color="#2563eb" />
        </TouchableOpacity>

        <TouchableOpacity
          style={styles.todayButton}
          onPress={() => setSelectedDate(new Date())}
        >
          <Text style={styles.todayButtonText}>Today</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={styles.navButton}
          onPress={() => {
            const newDate = new Date(selectedDate);
            if (viewMode === 'day') {
              newDate.setDate(newDate.getDate() + 1);
            } else {
              newDate.setDate(newDate.getDate() + 7);
            }
            setSelectedDate(newDate);
          }}
        >
          <Ionicons name="chevron-forward" size={24} color="#2563eb" />
        </TouchableOpacity>
      </View>

      <View style={styles.viewModeContainer}>
        <View style={styles.viewModeToggle}>
          <TouchableOpacity
            style={[styles.viewModeButton, viewMode === 'day' && styles.viewModeButtonActive]}
            onPress={() => setViewMode('day')}
          >
            <Ionicons
              name="today-outline"
              size={18}
              color={viewMode === 'day' ? '#fff' : '#6b7280'}
            />
            <Text style={[styles.viewModeText, viewMode === 'day' && styles.viewModeTextActive]}>
              Day
            </Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={[styles.viewModeButton, viewMode === 'week' && styles.viewModeButtonActive]}
            onPress={() => setViewMode('week')}
          >
            <Ionicons
              name="calendar-outline"
              size={18}
              color={viewMode === 'week' ? '#fff' : '#6b7280'}
            />
            <Text style={[styles.viewModeText, viewMode === 'week' && styles.viewModeTextActive]}>
              Week
            </Text>
          </TouchableOpacity>
        </View>
        <Text style={styles.jobsCount}>
          {filteredJobs.length} job{filteredJobs.length !== 1 ? 's' : ''}
        </Text>
      </View>

      {/* Week Header (only in week view) */}
      {viewMode === 'week' && (
        <WeekHeader weekDays={weekDays} selectedDate={selectedDate} />
      )}

      <ScrollView
        ref={scrollRef}
        style={styles.timeline}
        contentContainerStyle={styles.timelineContent}
        refreshControl={
          <RefreshControl
            refreshing={refreshing}
            onRefresh={onRefresh}
            colors={['#2563eb']}
            tintColor="#2563eb"
          />
        }
        onLayout={scrollToNow}
        showsVerticalScrollIndicator={true}
      >
        <TimelineGrid viewMode={viewMode} />

        {viewMode === 'day' && isSameDay(selectedDate, new Date()) && (
          <CurrentTimeLine viewMode={viewMode} />
        )}

        <View style={[
          styles.jobsContainer,
          viewMode === 'week' && styles.jobsContainerWeek,
        ]}>
          {viewMode === 'day' ? (
            dayJobsWithLanes.map((job) => (
              <DraggableJobBlock
                key={job.id}
                job={job}
                onPress={() => handleJobPress(job.id)}
                onTimeChange={handleTimeChange}
                canEdit={canEditSchedule}
                viewMode={viewMode}
                laneIndex={job.laneIndex}
                totalLanes={job.totalLanes}
              />
            ))
          ) : (
            Object.entries(jobsByDay).map(([dayIndex, jobs]) =>
              jobs.map((job) => (
                <DraggableJobBlock
                  key={job.id}
                  job={job}
                  onPress={() => handleJobPress(job.id)}
                  onTimeChange={handleTimeChange}
                  canEdit={false}
                  viewMode={viewMode}
                  dayIndex={parseInt(dayIndex)}
                  laneIndex={job.laneIndex}
                  totalLanes={job.totalLanes}
                />
              ))
            )
          )}
        </View>

        {filteredJobs.length === 0 && (
          <View style={styles.emptyOverlay}>
            <View style={styles.emptyContainer}>
              <Ionicons name="calendar-outline" size={48} color="#d1d5db" />
              <Text style={styles.emptyTitle}>No Jobs Scheduled</Text>
              <Text style={styles.emptyText}>
                Pull down to refresh
              </Text>
            </View>
          </View>
        )}
      </ScrollView>
    </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f9fafb',
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    backgroundColor: '#2563eb',
    paddingHorizontal: 16,
    paddingVertical: 16,
  },
  greeting: {
    fontSize: 20,
    fontWeight: '700',
    color: '#fff',
  },
  dateText: {
    fontSize: 14,
    color: 'rgba(255,255,255,0.8)',
    marginTop: 2,
  },
  logoutButton: {
    padding: 8,
    backgroundColor: 'rgba(255,255,255,0.2)',
    borderRadius: 8,
  },
  dateNavContainer: {
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
    paddingVertical: 8,
    gap: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#e5e7eb',
  },
  navButton: {
    padding: 8,
    borderRadius: 8,
    backgroundColor: '#f3f4f6',
  },
  todayButton: {
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 8,
    backgroundColor: '#eff6ff',
  },
  todayButtonText: {
    color: '#2563eb',
    fontWeight: '600',
    fontSize: 14,
  },
  viewModeContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    backgroundColor: '#fff',
    paddingHorizontal: 16,
    paddingVertical: 10,
    borderBottomWidth: 1,
    borderBottomColor: '#e5e7eb',
  },
  viewModeToggle: {
    flexDirection: 'row',
    backgroundColor: '#f3f4f6',
    borderRadius: 8,
    padding: 2,
  },
  viewModeButton: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 6,
    gap: 4,
  },
  viewModeButtonActive: {
    backgroundColor: '#2563eb',
  },
  viewModeText: {
    fontSize: 14,
    fontWeight: '500',
    color: '#6b7280',
  },
  viewModeTextActive: {
    color: '#fff',
  },
  jobsCount: {
    fontSize: 14,
    color: '#6b7280',
  },
  weekHeader: {
    flexDirection: 'row',
    backgroundColor: '#fff',
    borderBottomWidth: 1,
    borderBottomColor: '#e5e7eb',
    paddingVertical: 8,
  },
  weekHeaderSpacer: {
    width: 50,
  },
  weekDayHeader: {
    width: DAY_COLUMN_WIDTH,
    alignItems: 'center',
  },
  weekDayName: {
    fontSize: 11,
    color: '#9ca3af',
    fontWeight: '500',
  },
  weekDayNameToday: {
    color: '#2563eb',
  },
  weekDayNumber: {
    width: 28,
    height: 28,
    borderRadius: 14,
    alignItems: 'center',
    justifyContent: 'center',
    marginTop: 2,
  },
  weekDayNumberToday: {
    backgroundColor: '#2563eb',
  },
  weekDayNumberText: {
    fontSize: 14,
    fontWeight: '600',
    color: '#374151',
  },
  weekDayNumberTextToday: {
    color: '#fff',
  },
  timeline: {
    flex: 1,
  },
  timelineContent: {
    position: 'relative',
    minHeight: 24 * HOUR_HEIGHT,
    paddingBottom: 40,
  },
  timelineGrid: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
  },
  hourRow: {
    flexDirection: 'row',
    alignItems: 'flex-start',
    height: HOUR_HEIGHT,
  },
  hourLabel: {
    width: 50,
    fontSize: 11,
    color: '#9ca3af',
    textAlign: 'right',
    paddingRight: 8,
    paddingTop: 2,
  },
  hourLine: {
    flex: 1,
    height: 1,
    backgroundColor: '#e5e7eb',
    marginTop: 8,
  },
  currentTimeLine: {
    position: 'absolute',
    left: 42,
    right: 0,
    flexDirection: 'row',
    alignItems: 'center',
    zIndex: 10,
  },
  currentTimeDot: {
    width: 10,
    height: 10,
    borderRadius: 5,
    backgroundColor: '#ef4444',
  },
  currentTimeLineBar: {
    flex: 1,
    height: 2,
    backgroundColor: '#ef4444',
  },
  jobsContainer: {
    position: 'absolute',
    top: 0,
    left: 58,
    right: 12,
  },
  jobsContainerWeek: {
    left: 50,
    right: 0,
  },
  jobBlock: {
    position: 'absolute',
    backgroundColor: '#fff',
    borderRadius: 6,
    borderLeftWidth: 3,
    padding: 6,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
    elevation: 2,
    overflow: 'hidden',
  },
  jobBlockHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 2,
  },
  jobBlockTime: {
    fontSize: 10,
    color: '#6b7280',
    fontWeight: '500',
  },
  jobBlockTimeSmall: {
    fontSize: 9,
  },
  statusDot: {
    width: 6,
    height: 6,
    borderRadius: 3,
  },
  jobBlockTitle: {
    fontSize: 13,
    fontWeight: '600',
    color: '#111827',
    marginBottom: 2,
  },
  jobBlockTitleSmall: {
    fontSize: 10,
  },
  jobBlockCustomer: {
    fontSize: 11,
    color: '#4b5563',
  },
  jobBlockAddress: {
    fontSize: 10,
    color: '#9ca3af',
    marginTop: 2,
  },
  centerContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 24,
    backgroundColor: '#f9fafb',
  },
  loadingText: {
    marginTop: 12,
    fontSize: 16,
    color: '#6b7280',
  },
  errorText: {
    marginTop: 12,
    fontSize: 16,
    color: '#ef4444',
    textAlign: 'center',
  },
  retryButton: {
    marginTop: 16,
    backgroundColor: '#2563eb',
    paddingHorizontal: 24,
    paddingVertical: 12,
    borderRadius: 8,
  },
  retryButtonText: {
    color: '#fff',
    fontSize: 14,
    fontWeight: '600',
  },
  emptyOverlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    justifyContent: 'center',
    alignItems: 'center',
  },
  emptyContainer: {
    alignItems: 'center',
    backgroundColor: 'rgba(255,255,255,0.95)',
    padding: 32,
    borderRadius: 16,
  },
  emptyTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: '#6b7280',
    marginTop: 12,
  },
  emptyText: {
    fontSize: 14,
    color: '#9ca3af',
    marginTop: 4,
  },
});
