/**
 * @file GanttChart.tsx
 * @description プロジェクト管理システムのガントチャートコンポーネント
 * 
 * このコンポーネントは以下の機能を提供します：
 * - プロジェクトとアサインメントの視覚的な表示
 * - タスクのドラッグ＆ドロップによる順序変更
 * - タスクバーのリサイズによる期間調整
 * - 月別・日別の時間軸表示
 * - タスクの種別による色分け表示
 */

import React, { useState, useEffect, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { SortMenu } from './SortMenu';
import * as holiday_jp from '@holiday-jp/holiday_jp';
import { TaskBar } from '@/components/gantt/TaskBar';
import { CHART_SETTINGS, DISPLAY_RANGES, DisplayRangeType } from './constants';
import { PROJECT_STYLES, STATUS_STYLES, getBadgeStyle } from '@/styles/project-styles';

type Assignment = {
  id: string;
  worker: string;
  startDate: string;
  endDate: string;
  external: boolean;
  concurrent: boolean;
};

type Project = {
  id: string;
  name: string;
  type: string;
  leader: string;
  budget: number;
  assignments: Assignment[];
};

type Task = {
  id: string;
  name: string;
  start: number;
  duration: number;
  order: number;
  worker: string;
  type: string;
  projectId: string;
  external: boolean;
  concurrent: boolean;
  startDate: string;
  endDate: string;
};

// プロジェクトタイプの定義
const PROJECT_TYPES = {
  'Spine': 'bg-amber-100',
  '3D': 'bg-rose-100',
  '2D': 'bg-emerald-100',
  '研修': 'bg-orange-100'
} as const;

// TaskRow コンポーネント
const TaskRow = ({ 
  task, 
  scale, 
  taskHeight,
  isActive,
  isDragging,
  onBarStart,
  onInfoPress,
  onInfoDrag,
  onInfoDragEnd,
  startDate,
  dragOverId,
  tasks,
  draggingTask,
  hoverId,
  setHoverId
}: {
  task: Task;
  scale: number;
  taskHeight: number;
  isActive: boolean;
  isDragging: boolean;
  onBarStart: (e: any, task: Task, type: string) => void;
  onInfoPress: (e: any, task: Task) => void;
  onInfoDrag: (e: any) => void;
  onInfoDragEnd: () => void;
  startDate: Date;
  dragOverId: string | null;
  tasks: Task[];
  draggingTask: Task | null;
  hoverId: string | null;
  setHoverId: (id: string | null) => void;
}) => {
  // 日付を更新する関数
  const getUpdatedDates = (start: number, duration: number) => {
    const taskStartDate = new Date(startDate.getTime() + start * 24 * 60 * 60 * 1000);
    const taskEndDate = new Date(startDate.getTime() + (start + duration) * 24 * 60 * 60 * 1000);
    return {
      startDate: taskStartDate.toISOString().split('T')[0],
      endDate: taskEndDate.toISOString().split('T')[0]
    };
  };

  const isOver = dragOverId === task.id;
  const isBeingDragged = draggingTask?.id === task.id;
  const isHovered = hoverId === task.id && !draggingTask;
  const dragTask = tasks.find(t => t.id === draggingTask?.id);
  const isMovingUp = dragTask && dragTask.order > task.order;

  const getTaskStyle = () => ({
    transform: isHovered ? `translateX(2px) translateY(-2px)` : 'none',
    transition: 'all 0.15s ease-out',
    position: 'relative' as const,
    zIndex: isHovered || isBeingDragged ? 20 : 10,
    cursor: isHovered ? 'grab' : 'default',
    opacity: isBeingDragged ? 0.5 : 1,
  });

  return {
    TaskInfo: (
      <div
        data-task-id={task.id}
        className={`
          flex items-center cursor-move
          ${PROJECT_STYLES[task.type as keyof typeof PROJECT_STYLES]?.bg || 'bg-gray-50'}
          ${PROJECT_STYLES[task.type as keyof typeof PROJECT_STYLES]?.border || 'border-gray-200'}
          ${isOver && dragTask
            ? isMovingUp 
              ? 'border-t-4 border-b border-t-blue-400 border-b-gray-200' 
              : 'border-b-4 border-b-blue-400'
            : 'border-b border-gray-200'
          }
        `}
        style={{ 
          height: `${taskHeight}px`,
          lineHeight: 1,
          padding: '0 8px',
          margin: 0,
          transform: `translateY(${taskHeight * 0.1}px)`,
          ...getTaskStyle()
        }}
        draggable="true"
        onDragStart={(e) => onInfoPress(e, task)}
        onDragEnter={(e) => {
          e.preventDefault();
          if (draggingTask?.id === task.id) return;
          onInfoDrag(e);
        }}
        onDragOver={(e) => e.preventDefault()}
        onDrop={(e) => {
          e.preventDefault();
          onInfoDragEnd();
        }}
        onDragEnd={onInfoDragEnd}
        onMouseEnter={() => setHoverId(task.id)}
        onMouseLeave={() => setHoverId(null)}
      >
        <div className="flex flex-col justify-center w-full">
          <div className={`font-medium text-xs truncate leading-none ${PROJECT_STYLES[task.type as keyof typeof PROJECT_STYLES]?.text || 'text-gray-900'}`}>
            {task.name}
          </div>
          <div className="text-xs text-gray-600 leading-none mt-0.5 flex items-center gap-1">
            {getUpdatedDates(task.start, task.duration).startDate} ～ 
            {getUpdatedDates(task.start, task.duration).endDate}
            {task.external && <span className={getBadgeStyle('external')}>(外注)</span>}
            {task.concurrent && <span className={getBadgeStyle('concurrent')}>(兼任)</span>}
          </div>
        </div>
      </div>
    ),
    TaskBar: (
      <TaskBar
        task={task}
        scale={scale}
        taskHeight={taskHeight}
        isActive={isActive}
        onBarStart={onBarStart}
      />
    )
  };
};

type GanttChartProps = {
  projects: Project[];
  setProjects: React.Dispatch<React.SetStateAction<Project[]>>;
  setHasChanges: React.Dispatch<React.SetStateAction<boolean>>;
};

const GanttChart: React.FC<GanttChartProps> = ({ projects: initialProjects, setProjects: updateProjects, setHasChanges: updateHasChanges }) => {
  const chartRef = useRef(null);
  
  // 開始日を現在の日付の1ヶ月前に設定
  const initialStartDate = new Date();
  initialStartDate.setMonth(initialStartDate.getMonth() - 1);
  const [startDate, setStartDate] = useState<Date>(initialStartDate);
  
  const [projects, setProjects] = useState<Project[]>(initialProjects);
  const [tasks, setTasks] = useState<Task[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [activeTask, setActiveTask] = useState(null);
  const [dragType, setDragType] = useState(null);
  const [dragStart, setDragStart] = useState({ x: 0, offsetX: 0 });
  const [isDragging, setIsDragging] = useState(false);
  const [initialTaskState, setInitialTaskState] = useState(null);
  const [draggingTask, setDraggingTask] = useState(null);
  const [draggingPosition, setDraggingPosition] = useState(null);
  const [longPressTimer, setLongPressTimer] = useState(null);

  // 更新ボタンの状態
  const [isUpdating, setIsUpdating] = useState(false);
  const [hasChanges, setHasChanges] = useState(false);

  // ソートメニューの状態を追加
  const [showSortMenu, setShowSortMenu] = useState(false);

  // ドラッグ&ドロップの状態を追加
  const [dragOverId, setDragOverId] = useState<string | null>(null);
  const [hoverId, setHoverId] = useState<string | null>(null);

  // 表示範囲を4ヶ月（1ヶ月前から3ヶ月後まで）に設定
  const [displayRange, setDisplayRange] = useState<DisplayRangeType>('4months');

  const { days: VISIBLE_DAYS, scale: SCALE } = DISPLAY_RANGES[displayRange];
  const { TASK_HEIGHT = 40, HEADER_HEIGHT = 56, TASK_INFO_WIDTH = 300, TOTAL_DAYS } = CHART_SETTINGS;

  useEffect(() => {
    const fetchProjects = async () => {
      try {
        const response = await fetch('/api/projects');
        if (!response.ok) {
          throw new Error('プロジェクトの取得に失敗しました');
        }
        const data = await response.json();
        setProjects(data);

        // プロジェクトとアサインメントからタスクを生成
        const generatedTasks = data.flatMap((project, projectIndex) => {
          // プロジェクトごとのアサインメントをソート
          const sortedAssignments = [...project.assignments].sort((a, b) => {
            const aStart = new Date(a.startDate).getTime();
            const bStart = new Date(b.startDate).getTime();
            if (aStart !== bStart) return aStart - bStart;
            return a.worker.localeCompare(b.worker);
          });

          return sortedAssignments.map((assignment, assignmentIndex) => {
            const assignmentStart = new Date(assignment.startDate);
            const assignmentEnd = new Date(assignment.endDate);
            
            // 日数の計算を修正
            const daysDiff = Math.max(1, Math.floor((assignmentEnd.getTime() - assignmentStart.getTime()) / (1000 * 60 * 60 * 24)) + 1);
            const daysFromStart = Math.max(0, Math.floor((assignmentStart.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)));

            // orderの計算を修正
            const order = assignmentIndex + projectIndex * (project.assignments.length + 1);

            return {
              id: assignment.id,
              name: `${project.name} - ${assignment.worker}`,
              start: daysFromStart,
              duration: daysDiff,
              order: order,
              worker: assignment.worker,
              type: project.type,
              projectId: project.id,
              external: assignment.external,
              concurrent: assignment.concurrent,
              startDate: assignment.startDate,
              endDate: assignment.endDate
            };
          });
        });

        // タスクをorder順にソート
        const sortedTasks = generatedTasks.sort((a, b) => a.order - b.order);
        setTasks(sortedTasks);
      } catch (err) {
        setError(err instanceof Error ? err.message : '予期せぬエラーが発生しました');
      } finally {
        setLoading(false);
      }
    };

    fetchProjects();
  }, []);

  const getDateFromStart = (days) => {
    const date = new Date(startDate);
    date.setDate(date.getDate() + days);
    return date;
  };

  const isSaturday = (date) => {
    return date.getDay() === 6;
  };

  const isSunday = (date) => {
    return date.getDay() === 0;
  };

  const isHoliday = (date) => {
    return isSunday(date);
  };

  const getDateColor = (date) => {
    if (holiday_jp.isHoliday(date)) {
      return 'text-red-600';
    }
    const day = date.getDay();
    if (day === 0) return 'text-red-600';
    if (day === 6) return 'text-blue-600';
    return 'text-gray-600';
  };

  const isToday = (date) => {
    const today = new Date();
    return date.getFullYear() === today.getFullYear() &&
      date.getMonth() === today.getMonth() &&
      date.getDate() === today.getDate();
  };

  const formatDateSimple = (date: Date) => {
    return date.toISOString().split('T')[0];
  };

  const formatDate = (date) => {
    return date.toLocaleDateString('ja-JP', {
      month: '2-digit',
      day: '2-digit'
    });
  };

  const formatMonth = (date) => {
    return date.toLocaleDateString('ja-JP', { month: 'long' });
  };

  const formatDay = (date: Date) => {
    return date.getDate().toString();
  };

  const getMonthSpans = () => {
    const spans = [];
    let currentMonth = -1;
    let currentSpan = null;

    for (let i = 0; i < TOTAL_DAYS; i++) {
      const date = getDateFromStart(i);
      const month = date.getMonth();

      if (month !== currentMonth) {
        if (currentSpan) {
          spans.push(currentSpan);
        }
        currentSpan = {
          month: formatMonth(date),
          start: i,
          width: 1
        };
        currentMonth = month;
      } else {
        currentSpan.width++;
      }
    }
    spans.push(currentSpan);
    return spans;
  };

  const getRelativePosition = (e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent) => {
    const chartRect = chartRef.current.getBoundingClientRect();
    const point = 'touches' in e ? e.touches[0] : (e as MouseEvent);
    return {
      x: point.clientX - chartRect.left + chartRef.current.scrollLeft
    };
  };

  const handleBarStart = (e: React.MouseEvent | React.TouchEvent, task: Task, type: string) => {
    e.preventDefault();
    const position = getRelativePosition(e);
    const offsetX = position.x - (task.start * SCALE);
    
    setActiveTask(task);
    setDragType(type);
    setDragStart({ x: position.x, offsetX });
    setInitialTaskState({ ...task });
    setIsDragging(true);
  };

  useEffect(() => {
    const handleWheel = (e: WheelEvent) => {
      if (e.shiftKey) {
        e.preventDefault();
        if (chartRef.current) {
          chartRef.current.scrollLeft += e.deltaY;
        }
      }
    };

    const chartElement = chartRef.current;
    if (chartElement) {
      chartElement.addEventListener('wheel', handleWheel, { passive: false });
    }

    return () => {
      if (chartElement) {
        chartElement.removeEventListener('wheel', handleWheel);
      }
    };
  }, []);

  const handleMove = (e: MouseEvent | TouchEvent) => {
    if (!activeTask || !isDragging || !initialTaskState) return;
    
    if ('preventDefault' in e) {
      e.preventDefault();
    }
    
    const position = getRelativePosition(e);

    setTasks(prevTasks => {
      const updatedTasks = [...prevTasks];
      const activeIndex = updatedTasks.findIndex(t => t.id === activeTask.id);
      
      if (dragType === 'move') {
        const newStart = Math.max(0, Math.round((position.x - dragStart.offsetX) / SCALE));
        updatedTasks[activeIndex] = {
          ...updatedTasks[activeIndex],
          start: newStart
        };
      } else if (dragType === 'resize-start') {
        const newStart = Math.max(0, Math.round((position.x - dragStart.offsetX) / SCALE));
        const newDuration = Math.max(1, initialTaskState.duration - (newStart - initialTaskState.start));
        updatedTasks[activeIndex] = {
          ...updatedTasks[activeIndex],
          start: newStart,
          duration: newDuration
        };
      } else if (dragType === 'resize-end') {
        const diffX = position.x - dragStart.x;
        const newDuration = Math.max(1, initialTaskState.duration + Math.round(diffX / SCALE));
        updatedTasks[activeIndex] = {
          ...updatedTasks[activeIndex],
          duration: newDuration
        };
      }

      setHasChanges(true);
      return updatedTasks;
    });
  };

  const handleInfoPress = (e: React.DragEvent, task: Task) => {
    const dragImage = e.currentTarget.cloneNode(true) as HTMLElement;
    dragImage.style.width = `${e.currentTarget.clientWidth}px`;
    dragImage.style.height = `${TASK_HEIGHT}px`;
    document.body.appendChild(dragImage);
    e.dataTransfer.setDragImage(
      dragImage,
      e.clientX - e.currentTarget.getBoundingClientRect().left,
      e.clientY - e.currentTarget.getBoundingClientRect().top
    );
    setTimeout(() => document.body.removeChild(dragImage), 0);
    
    setDraggingTask(task);
  };

  const handleInfoDrag = (e: React.MouseEvent | React.TouchEvent) => {
    if (!draggingTask) return;

    const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;
    const elements = document.elementsFromPoint(
      'touches' in e ? e.touches[0].clientX : e.clientX,
      clientY
    );
    
    const taskElement = elements.find(el => el.hasAttribute('data-task-id'));
    if (taskElement) {
      const taskId = taskElement.getAttribute('data-task-id');
      if (taskId !== draggingTask.id) {
        setDragOverId(taskId);
      }
    }
  };

  const handleInfoDragEnd = () => {
    if (!draggingTask || !dragOverId) {
      setDraggingTask(null);
      setDragOverId(null);
      return;
    }

    const draggedIndex = tasks.findIndex(t => t.id === draggingTask.id);
    const dropIndex = tasks.findIndex(t => t.id === dragOverId);

    if (draggedIndex === -1 || dropIndex === -1) {
      setDraggingTask(null);
      setDragOverId(null);
      return;
    }

    const newTasks = [...tasks];
    const [draggedTask] = newTasks.splice(draggedIndex, 1);
    newTasks.splice(dropIndex, 0, draggedTask);

    // Update order property for all tasks
    const updatedTasks = newTasks.map((task, index) => ({
      ...task,
      order: index
    }));

    setTasks(updatedTasks);
    setHasChanges(true);
    setDraggingTask(null);
    setDragOverId(null);
  };

  const handleEnd = () => {
    setActiveTask(null);
    setDragType(null);
    setIsDragging(false);
    setInitialTaskState(null);
  };

  // 更新処理
  const handleUpdate = async () => {
    if (!hasChanges) return;
    
    setIsUpdating(true);
    try {
      // タスクの変更をアサインメントの更新データに変換
      const updates = tasks.map(task => ({
        id: task.id,
        startDate: new Date(startDate.getTime() + task.start * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
        endDate: new Date(startDate.getTime() + (task.start + task.duration) * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
        worker: task.worker,
        external: task.external,
        concurrent: task.concurrent
      }));

      // APIを呼び出してデータを更新
      const response = await fetch('/api/projects/assignments', {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ assignments: updates }),
      });

      if (!response.ok) {
        throw new Error('更新に失敗しました');
      }

      setHasChanges(false);
    } catch (err) {
      setError(err instanceof Error ? err.message : '予期せぬエラーが発生しました');
    } finally {
      setIsUpdating(false);
    }
  };

  // タスクの順序を更新する関数を追加
  const updateTaskOrder = (sourceTask: Task, targetTask: Task) => {
    setTasks(prevTasks => {
      const updatedTasks = [...prevTasks];
      const sourceOrder = sourceTask.order;
      const targetOrder = targetTask.order;

      // 移動方向に応じて順序を更新
      if (sourceOrder < targetOrder) {
        // 下に移動する場合
        updatedTasks.forEach(task => {
          if (task.id === sourceTask.id) {
            task.order = targetOrder;
          } else if (task.order > sourceOrder && task.order <= targetOrder) {
            task.order--;
          }
        });
      } else {
        // 上に移動する場合
        updatedTasks.forEach(task => {
          if (task.id === sourceTask.id) {
            task.order = targetOrder;
          } else if (task.order >= targetOrder && task.order < sourceOrder) {
            task.order++;
          }
        });
      }

      setHasChanges(true);
      return updatedTasks.sort((a, b) => a.order - b.order);
    });
  };

  // ドラッグ中のタスク情報を表示するコンポーネント
  const DragPreview = ({ task, position }) => {
    if (!position) return null;

    return (
      <div
        className="fixed pointer-events-none bg-white shadow-lg border border-gray-200 rounded p-2 z-50"
        style={{
          left: position.x + 10,
          top: position.y + 10,
          transform: 'scale(0.8)',
          opacity: 0.9
        }}
      >
        <div className="font-medium text-sm">{task.name}</div>
        <div className="text-xs text-gray-500">
          {formatDateSimple(new Date(task.startDate))} ～ {formatDateSimple(new Date(task.endDate))}
        </div>
      </div>
    );
  };

  // ソート機能を追加
  const handleSort = (sortType: string) => {
    setTasks(prevTasks => {
      let sortedTasks = [...prevTasks];
      
      switch (sortType) {
        case 'name':
          sortedTasks.sort((a, b) => a.name.localeCompare(b.name));
          break;
        case 'worker':
          sortedTasks.sort((a, b) => a.worker.localeCompare(b.worker));
          break;
        case 'type':
          sortedTasks.sort((a, b) => a.type.localeCompare(b.type));
          break;
        case 'order':
          sortedTasks.sort((a, b) => a.order - b.order);
          break;
      }
      
      // orderを更新
      return sortedTasks.map((task, index) => ({
        ...task,
        order: index
      }));
    });
    setShowSortMenu(false);
    setHasChanges(true);
  };

  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (isDragging) {
        handleMove(e);
      }
    };

    const handleMouseUp = () => {
      handleEnd();
    };

    if (isDragging) {
      document.addEventListener('mousemove', handleMouseMove);
      document.addEventListener('mouseup', handleMouseUp);
      document.addEventListener('touchmove', handleMove as any);
      document.addEventListener('touchend', handleEnd);

      return () => {
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
        document.removeEventListener('touchmove', handleMove as any);
        document.removeEventListener('touchend', handleEnd);
      };
    }
  }, [isDragging, dragStart]);

  if (loading) {
    return <div className="p-4">読み込み中...</div>;
  }

  if (error) {
    return <div className="p-4 text-red-600">{error}</div>;
  }

  const monthSpans = getMonthSpans();

  return (
    <div className="h-full flex flex-col">
      {/* スクロールショートカットガイド */}
      <div className="bg-gray-50 border-b px-4 py-2 text-sm text-gray-600 flex items-center">
        <div className="flex items-center gap-1">
          <kbd className="px-2 py-1 bg-white rounded border shadow-sm">Shift</kbd>
          <span>+</span>
          <kbd className="px-2 py-1 bg-white rounded border shadow-sm">スクロール</kbd>
          <span className="ml-1">横スクロール</span>
        </div>
      </div>

      <div className="flex justify-between items-center p-4 bg-white border-b">
        <div className="flex items-center gap-2">
          <SortMenu handleSort={handleSort} />
          <div className="flex items-center gap-2 ml-4">
            <Button
              variant={displayRange === '1month' ? 'default' : 'outline'}
              onClick={() => setDisplayRange('1month')}
              className="text-sm"
            >
              3週間
            </Button>
            <Button
              variant={displayRange === '2months' ? 'default' : 'outline'}
              onClick={() => setDisplayRange('2months')}
              className="text-sm"
            >
              1ヶ月半
            </Button>
            <Button
              variant={displayRange === '4months' ? 'default' : 'outline'}
              onClick={() => setDisplayRange('4months')}
              className="text-sm"
            >
              3ヶ月
            </Button>
          </div>
        </div>
        {hasChanges && (
          <Button
            onClick={handleUpdate}
            disabled={isUpdating}
            className="text-sm"
          >
            {isUpdating ? '更新中...' : '変更を確定'}
          </Button>
        )}
      </div>
      
      <div className="flex-1 overflow-hidden">
        <div className="w-full h-full border border-gray-200">
          <div className="flex h-full">
            {/* Task info header */}
            <div className="flex-none border-r border-gray-200 bg-gray-50" style={{ width: `${TASK_INFO_WIDTH}px` }}>
              <div className="sticky top-0 z-10">
                <div className="px-2 text-sm font-semibold" style={{ padding: '22px 0' }}>　案件名 - 作業者</div>
              </div>
              <div className="overflow-y-auto" style={{ height: 'calc(100% - 56px)' }}>
                {tasks.sort((a, b) => a.order - b.order).map((task) => (
                  <div
                    key={`task-info-${task.id}`}
                    className="border-b border-gray-200"
                    style={{ height: `${TASK_HEIGHT}px` }}
                  >
                    {TaskRow({
                      task,
                      scale: SCALE,
                      taskHeight: TASK_HEIGHT,
                      isActive: activeTask?.id === task.id,
                      isDragging: draggingTask?.id === task.id,
                      onBarStart: handleBarStart,
                      onInfoPress: handleInfoPress,
                      onInfoDrag: handleInfoDrag,
                      onInfoDragEnd: handleInfoDragEnd,
                      startDate,
                      dragOverId,
                      tasks,
                      draggingTask,
                      hoverId,
                      setHoverId
                    }).TaskInfo}
                  </div>
                ))}
              </div>
            </div>

            {/* Gantt chart area */}
            <div className="flex-1 flex flex-col overflow-hidden">
              {/* スクロール可能なエリア */}
              <div 
                ref={chartRef}
                className="flex-1 overflow-auto"
              >
                <div style={{ width: `${TOTAL_DAYS * SCALE}px`, position: 'relative' }}>
                  {/* Header */}
                  <div className="sticky top-0 z-10 bg-white">
                    {/* Month row */}
                    <div className="flex h-8 border-b border-gray-200">
                      {monthSpans.map((span, i) => (
                        <div
                          key={`month-${i}`}
                          className="flex-none border-r border-gray-200 px-2 font-medium"
                          style={{ width: `${span.width * SCALE}px` }}
                        >
                          {span.month}
                        </div>
                      ))}
                    </div>
                    {/* Day row */}
                    <div className="flex h-8 border-b border-gray-200">
                      {Array.from({ length: TOTAL_DAYS }).map((_, i) => {
                        const date = getDateFromStart(i);
                        const day = date.getDate();
                        const shouldShowDate = displayRange !== '4months' || day % 2 === 1;
                        return (
                          <div
                            key={`day-${i}`}
                            className={`flex-none border-r border-gray-200 text-sm ${getDateColor(date)}`}
                            style={{ 
                              width: `${SCALE}px`,
                              display: 'flex',
                              justifyContent: 'center',
                              alignItems: 'center'
                            }}
                          >
                            {shouldShowDate && formatDay(date)}
                            {isToday(date) && (
                              <div className="absolute inset-0 bg-blue-100 opacity-30" />
                            )}
                          </div>
                        );
                      })}
                    </div>
                  </div>

                  {/* Grid lines */}
                  {Array.from({ length: TOTAL_DAYS + 1 }).map((_, i) => {
                    const date = getDateFromStart(i);
                    const isCurrentDate = isToday(date);
                    return (
                      <div
                        key={`grid-${i}`}
                        className={`absolute top-16 bottom-0 border-l
                          ${isCurrentDate ? 'border-red-500 border-l-2' : 'border-gray-200'}`}
                        style={{ 
                          left: `${i * SCALE}px`,
                          zIndex: isCurrentDate ? 2 : 1
                        }}
                      />
                    );
                  })}
                  
                  {/* Task bars */}
                  <div style={{ paddingTop: '16px' }}>
                    {tasks.sort((a, b) => a.order - b.order).map((task) => (
                      <div 
                        key={`task-bar-${task.id}`}
                        className="relative"
                        style={{ height: `${TASK_HEIGHT}px` }}
                      >
                        {TaskRow({
                          task,
                          scale: SCALE,
                          taskHeight: TASK_HEIGHT,
                          isActive: activeTask?.id === task.id,
                          isDragging: draggingTask?.id === task.id,
                          onBarStart: handleBarStart,
                          onInfoPress: handleInfoPress,
                          onInfoDrag: handleInfoDrag,
                          onInfoDragEnd: handleInfoDragEnd,
                          startDate,
                          dragOverId,
                          tasks,
                          draggingTask,
                          hoverId,
                          setHoverId
                        }).TaskBar}
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export { GanttChart };
