import React, { useState, useMemo } from "react";
import { useQuery } from "@tanstack/react-query";
import Layout from "@/components/layout/layout";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { CustomSelect } from "@/components/ui/custom-select";
import { Label } from "@/components/ui/label";
import { projectService, ganttChartService, employeeService, GanttChartResponseDto, GanttDeliverableDto, GanttFeatureDto, GanttTaskDto } from "@/lib/api";
import { ChevronRight, ChevronDown, User, Loader2 } from "lucide-react";
import { cn } from "@/lib/utils";
import { toast } from "@/lib/custom-toast";
import { format, parseISO, differenceInDays, addDays, eachDayOfInterval } from "date-fns";

interface GanttTaskNameProps {
  level: number;
  name: string;
  assignee?: string | null;
  hasChildren: boolean;
  isExpanded?: boolean;
  onToggle?: () => void;
}

const GanttTaskName: React.FC<GanttTaskNameProps> = ({ level, name, assignee, hasChildren, isExpanded, onToggle }) => {
  const levelColors = [
    { text: "text-blue-700", bg: "bg-blue-50", label: "Deliverable" },
    { text: "text-green-700", bg: "bg-green-50", label: "Feature" },
    { text: "text-purple-700", bg: "bg-purple-50", label: "Task" },
  ];

  const color = levelColors[level] || levelColors[2];

  return (
    <div className="border-b border-gray-200 p-3 hover:bg-gray-50 min-h-[60px] flex items-center" style={{ paddingLeft: `${level * 20 + 12}px` }}>
      {hasChildren && (
        <button
          onClick={onToggle}
          className="flex-shrink-0 hover:bg-gray-200 rounded p-1 mr-2 transition-colors"
        >
          {isExpanded ? (
            <ChevronDown className="h-4 w-4" />
          ) : (
            <ChevronRight className="h-4 w-4" />
          )}
        </button>
      )}
      {!hasChildren && <div className="w-6 mr-2" />}
      
      <div className="flex-1 min-w-0">
        <div className="flex items-center gap-2 mb-1">
          <span className={cn("text-xs font-medium px-1.5 py-0.5 rounded", color.text, color.bg)}>
            {color.label}
          </span>
        </div>
        <div className="font-medium text-sm truncate">{name || "Unnamed"}</div>
        {assignee && (
          <div className="flex items-center gap-1 text-xs text-gray-600 mt-1">
            <User className="h-3 w-3" />
            <span>{assignee}</span>
          </div>
        )}
      </div>
    </div>
  );
};

interface GanttBarProps {
  level: number;
  start?: string | null;
  end?: string | null;
  projectStart: Date;
  totalDays: number;
}

const GanttBar: React.FC<GanttBarProps> = ({ level, start, end, projectStart, totalDays }) => {
  const { barStyle, duration } = useMemo(() => {
    if (!start || !end) return { barStyle: null, duration: 0 };
    
    try {
      const startDate = parseISO(start);
      const endDate = parseISO(end);
      
      const daysFromStart = differenceInDays(startDate, projectStart);
      const taskDuration = differenceInDays(endDate, startDate) + 1;
      
      const leftPixels = daysFromStart * 40; // 40px per day
      const widthPixels = taskDuration * 40;
      
      return {
        barStyle: {
          left: `${leftPixels}px`,
          width: `${widthPixels}px`
        },
        duration: taskDuration
      };
    } catch (error) {
      return { barStyle: null, duration: 0 };
    }
  }, [start, end, projectStart, totalDays]);

  const levelColors = [
    { bg: "bg-blue-500", hover: "hover:bg-blue-600" },
    { bg: "bg-green-500", hover: "hover:bg-green-600" },
    { bg: "bg-purple-500", hover: "hover:bg-purple-600" },
  ];

  const color = levelColors[level] || levelColors[2];

  return (
    <div className="relative border-b border-gray-200 min-h-[60px] flex items-center">
      {barStyle && (
        <div
          className={cn(
            "absolute h-8 rounded shadow-sm flex items-center justify-center text-white text-xs font-medium transition-colors",
            color.bg,
            color.hover
          )}
          style={barStyle}
          title={start && end ? `${format(parseISO(start), 'MMM d, yyyy')} - ${format(parseISO(end), 'MMM d, yyyy')}` : ''}
        >
          <span className="truncate px-2">
            {start && end && duration > 3 && `${format(parseISO(start), 'MMM d')} - ${format(parseISO(end), 'MMM d')}`}
          </span>
        </div>
      )}
      {/* Background grid lines for each day */}
      <div className="absolute inset-0 flex pointer-events-none">
        {Array.from({ length: totalDays }).map((_, index) => (
          <div
            key={index}
            className="border-r border-gray-100 flex-shrink-0"
            style={{ width: "40px" }}
          />
        ))}
      </div>
    </div>
  );
};

const GanttChart = () => {
  const [selectedProjectId, setSelectedProjectId] = useState<string>("");
  const [selectedEmployeeId, setSelectedEmployeeId] = useState<string>("");
  const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
  const leftScrollRef = React.useRef<HTMLDivElement>(null);
  const rightScrollRef = React.useRef<HTMLDivElement>(null);

  const toggleExpand = (id: string) => {
    setExpandedItems(prev => {
      const newSet = new Set(prev);
      if (newSet.has(id)) {
        newSet.delete(id);
      } else {
        newSet.add(id);
      }
      return newSet;
    });
  };

  const { data: projects = [], isLoading: isLoadingProjects } = useQuery({
    queryKey: ["projects"],
    queryFn: async () => {
      try {
        return await projectService.getAll();
      } catch (error) {
        console.error("Failed to fetch projects:", error);
        toast.error("Failed to load projects");
        return [];
      }
    },
  });

  const { data: employees = [], isLoading: isLoadingEmployees } = useQuery({
    queryKey: ["employees"],
    queryFn: async () => {
      try {
        return await employeeService.getAll();
      } catch (error) {
        console.error("Failed to fetch employees:", error);
        throw error;
      }
    },
  });

  // Convert projects to CustomSelect options
  const projectOptions = projects.map((project) => ({
    value: String(project.id),
    label: project.projectName || `Project ${project.id}`,
  }));

  // Synchronize vertical scroll - only right panel scrolls, left follows
  const handleRightScroll = () => {
    if (leftScrollRef.current && rightScrollRef.current) {
      // Apply negative transform to left panel to simulate scroll
      const scrollTop = rightScrollRef.current.scrollTop;
      leftScrollRef.current.style.transform = `translateY(-${scrollTop}px)`;
    }
  };

  const { data: ganttData, isLoading: isLoadingGantt, error: ganttError } = useQuery({
    queryKey: ["ganttChart", selectedProjectId],
    queryFn: async () => {
      if (!selectedProjectId) return null;
      try {
        return await ganttChartService.getByProjectId(Number(selectedProjectId));
      } catch (error) {
        console.error("Failed to fetch Gantt chart data:", error);
        toast.error("Failed to load Gantt chart data");
        throw error;
      }
    },
    enabled: !!selectedProjectId,
  });

  // Get unique employees from the current project's Gantt data
  const projectEmployees = useMemo(() => {
    if (!ganttData?.deliverables) return [];

    const employeeNames = new Set<string>();

    ganttData.deliverables.forEach((deliverable) => {
      deliverable.features.forEach((feature) => {
        if (feature.assignee) employeeNames.add(feature.assignee);
        feature.tasks.forEach((task) => {
          if (task.assignee) employeeNames.add(task.assignee);
        });
      });
    });

    // Match employee names to employee IDs
    const projectEmployeeList = employees.filter((employee: any) => {
      const fullName = `${employee.firstName} ${employee.lastName}`;
      return employeeNames.has(fullName);
    });

    return projectEmployeeList;
  }, [ganttData, employees]);

  // Convert project employees to CustomSelect options
  const employeeOptions = useMemo(() => [
    { value: "", label: "All Employees" },
    ...projectEmployees.map((employee: any) => ({
      value: String(employee.id),
      label: `${employee.firstName} ${employee.lastName}`,
    }))
  ], [projectEmployees]);

  // Filter Gantt data based on selected employee
  const filteredGanttData = useMemo(() => {
    if (!ganttData || !selectedEmployeeId) return ganttData;

    const selectedEmployee = employees.find((emp: any) => String(emp.id) === selectedEmployeeId);
    if (!selectedEmployee) return ganttData;

    const employeeName = `${selectedEmployee.firstName} ${selectedEmployee.lastName}`;

    // Filter deliverables and their nested features/tasks
    const filteredDeliverables = ganttData.deliverables.map((deliverable) => {
      const filteredFeatures = deliverable.features
        .filter((feature) => feature.assignee === employeeName)
        .map((feature) => {
          const filteredTasks = feature.tasks.filter(
            (task) => task.assignee === employeeName
          );
          return { ...feature, tasks: filteredTasks };
        });

      // Also include features where tasks match the employee
      const featuresWithMatchingTasks = deliverable.features
        .filter((feature) => feature.assignee !== employeeName)
        .map((feature) => {
          const filteredTasks = feature.tasks.filter(
            (task) => task.assignee === employeeName
          );
          return filteredTasks.length > 0 ? { ...feature, tasks: filteredTasks } : null;
        })
        .filter((f) => f !== null);

      const allFilteredFeatures = [...filteredFeatures, ...featuresWithMatchingTasks];

      return allFilteredFeatures.length > 0
        ? { ...deliverable, features: allFilteredFeatures }
        : null;
    }).filter((d) => d !== null) as GanttDeliverableDto[];

    return { ...ganttData, deliverables: filteredDeliverables };
  }, [ganttData, selectedEmployeeId, employees]);

  // Calculate project timeline bounds
  const timelineBounds = useMemo(() => {
    if (!filteredGanttData?.deliverables || filteredGanttData.deliverables.length === 0) {
      return null;
    }

    const allDates: Date[] = [];

    filteredGanttData.deliverables.forEach((deliverable) => {
      if (deliverable.start) allDates.push(parseISO(deliverable.start));
      if (deliverable.end) allDates.push(parseISO(deliverable.end));

      deliverable.features.forEach((feature) => {
        if (feature.start) allDates.push(parseISO(feature.start));
        if (feature.end) allDates.push(parseISO(feature.end));

        feature.tasks.forEach((task) => {
          if (task.start) allDates.push(parseISO(task.start));
          if (task.end) allDates.push(parseISO(task.end));
        });
      });
    });

    if (allDates.length === 0) return null;

    const minDate = new Date(Math.min(...allDates.map(d => d.getTime())));
    const maxDate = new Date(Math.max(...allDates.map(d => d.getTime())));

    const projectStart = minDate;
    const projectEnd = maxDate;
    const totalDays = differenceInDays(projectEnd, projectStart) + 1;

    const days = eachDayOfInterval({ start: projectStart, end: projectEnd });

    return {
      projectStart,
      projectEnd,
      totalDays,
      days,
    };
  }, [filteredGanttData]);

  return (
    <Layout>
      <div className="container mx-auto py-6 space-y-6">
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-3xl font-bold tracking-tight">Gantt Chart</h1>
            <p className="text-muted-foreground mt-1">
              View project timeline with deliverables, features, and tasks
            </p>
          </div>
        </div>

        <Card>
            <CardHeader>
              <div className="flex items-center justify-between">
                <div>
                  <CardTitle>Timeline View</CardTitle>
                  <CardDescription>
                    Hierarchical view of deliverables, features, and tasks
                  </CardDescription>
                </div>
                <div className="flex items-center gap-3">
                  <div className="w-64">
                    <CustomSelect
                      options={projectOptions}
                      value={selectedProjectId}
                      onChange={setSelectedProjectId}
                      placeholder="Select project..."
                      disabled={isLoadingProjects}
                      className="w-full"
                    />
                  </div>
                  <div className="w-64">
                    <CustomSelect
                      options={employeeOptions}
                      value={selectedEmployeeId}
                      onChange={setSelectedEmployeeId}
                      placeholder="Filter by employee..."
                      disabled={isLoadingEmployees}
                      className="w-full"
                    />
                  </div>
                </div>
              </div>
            </CardHeader>
            <CardContent>
              {isLoadingGantt ? (
                <div className="flex items-center justify-center py-12">
                  <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
                  <span className="ml-2 text-muted-foreground">Loading Gantt chart...</span>
                </div>
              ) : ganttError ? (
                <div className="text-center py-12">
                  <p className="text-red-500">Failed to load Gantt chart data</p>
                  <p className="text-sm text-muted-foreground mt-2">
                    Please try selecting a different project
                  </p>
                </div>
              ) : !filteredGanttData?.deliverables || filteredGanttData.deliverables.length === 0 ? (
                <div className="text-center py-12">
                  <p className="text-muted-foreground">
                    {selectedEmployeeId ? "No data available for the selected employee" : "No data available for this project"}
                  </p>
                  <p className="text-sm text-muted-foreground mt-2">
                    {selectedEmployeeId ? "Try selecting a different employee or clear the filter" : "Add deliverables, features, and tasks to see the timeline"}
                  </p>
                </div>
              ) : !timelineBounds ? (
                <div className="text-center py-12">
                  <p className="text-muted-foreground">No valid dates found for this project</p>
                </div>
              ) : (
                <div className="border rounded-lg overflow-hidden bg-white">
                  {/* Single Scroll Container */}
                  <div className="max-h-[600px] overflow-auto" ref={rightScrollRef}>
                    <div style={{ minWidth: `${80 * 16 + timelineBounds.days.length * 40}px` }}>
                      {/* Headers Row */}
                      <div className="flex border-b-2 border-gray-300 bg-gray-50 sticky top-0 z-20">
                        <div className="w-80 flex-shrink-0 border-r-2 border-gray-300 p-3 font-semibold">
                          Task Name
                        </div>
                        <div className="flex">
                          {timelineBounds.days.map((day, index) => {
                            const isWeekend = day.getDay() === 0 || day.getDay() === 6;
                            return (
                              <div
                                key={index}
                                className={cn(
                                  "border-r border-gray-300 p-2 text-center font-semibold text-xs flex-shrink-0",
                                  isWeekend && "bg-gray-100"
                                )}
                                style={{ width: "40px" }}
                              >
                                <div className="text-[10px] text-gray-600">{format(day, 'EEE')}</div>
                                <div>{format(day, 'd')}</div>
                                <div className="text-[9px] text-gray-500">{format(day, 'MMM')}</div>
                              </div>
                            );
                          })}
                        </div>
                      </div>

                      {/* Content Rows */}
                      <div>
                      {filteredGanttData.deliverables.map((deliverable) => {
                        const deliverableId = `deliverable-${deliverable.id}`;
                        const isDeliverableExpanded = expandedItems.has(deliverableId);
                        
                        return (
                          <React.Fragment key={deliverableId}>
                            {/* Deliverable Row */}
                            <div className={cn(
                              "flex border-b border-gray-200 hover:bg-gray-50",
                              (!deliverable.start || !deliverable.end) && "bg-red-50 border-l-4 border-l-red-500"
                            )}>
                              <div className="w-80 flex-shrink-0 border-r border-gray-200 px-2 py-1.5 flex items-center" style={{ paddingLeft: "8px" }}>
                                {deliverable.features.length > 0 && (
                                  <button
                                    onClick={() => toggleExpand(deliverableId)}
                                    className="flex-shrink-0 hover:bg-gray-200 rounded p-0.5 mr-1.5 transition-colors"
                                  >
                                    {isDeliverableExpanded ? (
                                      <ChevronDown className="h-3.5 w-3.5" />
                                    ) : (
                                      <ChevronRight className="h-3.5 w-3.5" />
                                    )}
                                  </button>
                                )}
                                {deliverable.features.length === 0 && <div className="w-5 mr-1.5" />}
                                <div className="flex-1 min-w-0">
                                  <div className="flex items-center gap-1.5">
                                    <span className="text-[10px] font-medium px-1 py-0.5 rounded text-blue-700 bg-blue-50">
                                      Deliverable
                                    </span>
                                    <span className={cn(
                                      "font-medium text-xs truncate",
                                      (!deliverable.start || !deliverable.end) && "text-red-700"
                                    )}>{deliverable.name || "Unnamed"}</span>
                                    {(!deliverable.start || !deliverable.end) && (
                                      <span className="text-[9px] text-red-600 font-medium">⚠ Missing dates</span>
                                    )}
                                  </div>
                                </div>
                              </div>
                              <div className="flex-1 relative min-h-[36px] flex items-center">
                                <GanttBar
                                  level={0}
                                  start={deliverable.start}
                                  end={deliverable.end}
                                  projectStart={timelineBounds.projectStart}
                                  totalDays={timelineBounds.totalDays}
                                />
                              </div>
                            </div>

                            {/* Features */}
                            {isDeliverableExpanded && deliverable.features.map((feature) => {
                              const featureId = `feature-${feature.id}`;
                              const isFeatureExpanded = expandedItems.has(featureId);
                              
                              return (
                                <React.Fragment key={featureId}>
                                  {/* Feature Row */}
                                  <div className={cn(
                                    "flex border-b border-gray-200 hover:bg-gray-50",
                                    (!feature.start || !feature.end) && "bg-red-50 border-l-4 border-l-red-500"
                                  )}>
                                    <div className="w-80 flex-shrink-0 border-r border-gray-200 px-2 py-1.5 flex items-center" style={{ paddingLeft: "24px" }}>
                                      {feature.tasks.length > 0 && (
                                        <button
                                          onClick={() => toggleExpand(featureId)}
                                          className="flex-shrink-0 hover:bg-gray-200 rounded p-0.5 mr-1.5 transition-colors"
                                        >
                                          {isFeatureExpanded ? (
                                            <ChevronDown className="h-3.5 w-3.5" />
                                          ) : (
                                            <ChevronRight className="h-3.5 w-3.5" />
                                          )}
                                        </button>
                                      )}
                                      {feature.tasks.length === 0 && <div className="w-5 mr-1.5" />}
                                      <div className="flex-1 min-w-0">
                                        <div className="flex items-center gap-1.5 flex-wrap">
                                          <span className="text-[10px] font-medium px-1 py-0.5 rounded text-green-700 bg-green-50">
                                            Feature
                                          </span>
                                          <span className={cn(
                                            "font-medium text-xs truncate",
                                            (!feature.start || !feature.end) && "text-red-700"
                                          )}>{feature.name || "Unnamed"}</span>
                                          {feature.assignee && (
                                            <span className="flex items-center gap-0.5 text-[10px] text-gray-600">
                                              <User className="h-2.5 w-2.5" />
                                              {feature.assignee}
                                            </span>
                                          )}
                                          {(!feature.start || !feature.end) && (
                                            <span className="text-[9px] text-red-600 font-medium">⚠ Missing dates</span>
                                          )}
                                        </div>
                                      </div>
                                    </div>
                                    <div className="flex-1 relative min-h-[36px] flex items-center">
                                      <GanttBar
                                        level={1}
                                        start={feature.start}
                                        end={feature.end}
                                        projectStart={timelineBounds.projectStart}
                                        totalDays={timelineBounds.totalDays}
                                      />
                                    </div>
                                  </div>

                                  {/* Tasks */}
                                  {isFeatureExpanded && feature.tasks.map((task) => (
                                    <div key={`task-${task.id}`} className={cn(
                                      "flex border-b border-gray-200 hover:bg-gray-50",
                                      (!task.start || !task.end) && "bg-red-50 border-l-4 border-l-red-500"
                                    )}>
                                      <div className="w-80 flex-shrink-0 border-r border-gray-200 px-2 py-1.5 flex items-center" style={{ paddingLeft: "40px" }}>
                                        <div className="w-5 mr-1.5" />
                                        <div className="flex-1 min-w-0">
                                          <div className="flex items-center gap-1.5 flex-wrap">
                                            <span className="text-[10px] font-medium px-1 py-0.5 rounded text-purple-700 bg-purple-50">
                                              Task
                                            </span>
                                            <span className={cn(
                                              "font-medium text-xs truncate",
                                              (!task.start || !task.end) && "text-red-700"
                                            )}>{task.name || "Unnamed"}</span>
                                            {task.assignee && (
                                              <span className="flex items-center gap-0.5 text-[10px] text-gray-600">
                                                <User className="h-2.5 w-2.5" />
                                                {task.assignee}
                                              </span>
                                            )}
                                            {(!task.start || !task.end) && (
                                              <span className="text-[9px] text-red-600 font-medium">⚠ Missing dates</span>
                                            )}
                                          </div>
                                        </div>
                                      </div>
                                      <div className="flex-1 relative min-h-[36px] flex items-center">
                                        <GanttBar
                                          level={2}
                                          start={task.start}
                                          end={task.end}
                                          projectStart={timelineBounds.projectStart}
                                          totalDays={timelineBounds.totalDays}
                                        />
                                      </div>
                                    </div>
                                  ))}
                                </React.Fragment>
                              );
                            })}
                          </React.Fragment>
                        );
                      })}
                      </div>
                    </div>
                  </div>
                </div>
              )}
            </CardContent>
          </Card>
      </div>
    </Layout>
  );
};

export default GanttChart;
