"use client";

import React, { useState, useEffect, useMemo } from "react";
import { format } from "date-fns";
import { formatDate } from "@/app/utils/mapping-functions/date-format";
import {
  Gantt,
  GanttWeekView,
  GanttMonthView,
  GanttTaskClickEvent,
  GanttExpandChangeEvent,
  GanttViewTimelineHeaderCellProps,
} from "@progress/kendo-react-gantt";
import { getScheduleApi } from "@/app/utils/api/projectApi";

interface TaskDto {
  id: number;
  parentId?: number;
  taskName?: string;
  taskStart?: string;
  taskEnd?: string;
  taskDuration?: number | null;
  taskDescription?: string;
  taskColour?: string;
  taskPredecessor?: string;
  dependencyType?: number;
}

interface GroupItem {
  taskIds?: number[];
  groupName?: string;
  color?: string;
}

interface ScheduleGanttShowProps {
  projectIdentifier: string;
  onTaskSelect?: (taskId: number) => void;
}

const taskModelFields = {
  id: "id",
  start: "start",
  end: "end",
  title: "title",
  percentComplete: "percentComplete",
  isRollup: "isRollup",
  isExpanded: "isExpanded",
  children: "children",
};

const dependencyModelFields = {
  id: "id",
  fromId: "fromId",
  toId: "toId",
  type: "type",
};

const columns = [
  { field: "title", title: "Schedule", width: 130, expandable: true },
  { field: "start", title: "Start Date", width: 120, format: "{0:dd-MMM-yyyy}" },
  { field: "end", title: "End Date", width: 120, format: "{0:dd-MMM-yyyy}" },
  { field: "taskDescription", title: "Description", width: 180 },
];

type GanttTaskRow = {
  id: number | string;
  start: Date;
  end: Date;
  title: string;
  percentComplete: number;
  isRollup: boolean;
  isExpanded: boolean;
  taskDuration: number | null;
  taskDescription: string;
  color: string;
  rawPredecessor?: string;
  rawDepType?: number;
  _isGroup?: boolean;
  children?: GanttTaskRow[];
};

// Month view header cell: shows "May, 2026" instead of just "May"
const MonthViewHeaderCell: React.FC<GanttViewTimelineHeaderCellProps> = ({ range, rowIndex, text }) => {
  if (rowIndex === 0) {
    return <span>{format(range.start, "MMM, yyyy")}</span>;
  }
  return <span>{text}</span>;
};

const ScheduleGanttShowComponent: React.FC<ScheduleGanttShowProps> = ({
  projectIdentifier,
  onTaskSelect,
}) => {
  const [scheduleData, setScheduleData] = useState<GanttTaskRow[]>([]);
  const [dependencyData, setDependencyData] = useState<{ id: number; fromId: number; toId: number | string; type: number }[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
  const [tooltipTask, setTooltipTask] = useState<GanttTaskRow | null>(null);
  const [tooltipPos, setTooltipPos] = useState({ x: 0, y: 0 });
  const [allTasksFlat, setAllTasksFlat] = useState<GanttTaskRow[]>([]);

  const handleGanttMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
    setTooltipPos({ x: e.clientX, y: e.clientY });
  };

  const handleGanttMouseOver = (e: React.MouseEvent<HTMLDivElement>) => {
    let el = e.target as HTMLElement | null;
    while (el) {
      if (el.classList.contains("k-task-single") || el.classList.contains("k-task-milestone")) break;
      if (el.classList.contains("k-gantt-rows") || el === e.currentTarget) { el = null; break; }
      el = el.parentElement;
    }
    if (!el) { setTooltipTask(null); return; }
    const contentEl = el.querySelector(".k-task-content") || el;
    const title = contentEl.textContent?.trim() || "";
    const found = allTasksFlat.find(t => t.title === title) || null;
    setTooltipTask(found);
  };

  useEffect(() => {
    const fetchData = async () => {
      if (!projectIdentifier) return;

      setLoading(true);
      try {
        const scheduleResponse = await getScheduleApi(projectIdentifier);

        console.log("scheduleResponse", scheduleResponse);


        const backendTasks: TaskDto[] = scheduleResponse?.task || [];
        const backendGroups: Record<string, GroupItem> = scheduleResponse?.group || {};

        // Map raw tasks to GanttTaskRow objects
        const parseLocalDate = (dateStr: string | null | undefined): Date | null => {
          if (!dateStr) return null;
          if (dateStr.includes("T") || dateStr.includes(" ")) {
            const d = new Date(dateStr);
            return isNaN(d.getTime()) ? null : d;
          }
          const parts = dateStr.split("-").map(Number);
          if (parts.length < 3 || parts.some(isNaN)) return null;
          return new Date(parts[0], parts[1] - 1, parts[2], 12, 0, 0);
        };

        const taskById = new Map<number, GanttTaskRow>();
        backendTasks.forEach((task: TaskDto) => {
          const startDate = parseLocalDate(task.taskStart);
          if (!startDate || isNaN(startDate.getTime())) return;
          let endDate = parseLocalDate(task.taskEnd);
          if (!endDate || isNaN(endDate.getTime())) {
            endDate = new Date(startDate.getTime() + 86400000);
          }
          taskById.set(task.id, {
            id: task.id,
            start: startDate,
            end: endDate,
            title: task.taskName || "Untitled Task",
            percentComplete: 0,
            isRollup: false,
            isExpanded: true,
            taskDuration: task.taskDuration ?? null,
            taskDescription: task.taskDescription || "",
            color: task.taskColour || "#84d5f7",
            rawPredecessor: task.taskPredecessor,
            rawDepType: task.dependencyType,
            _isGroup: false,
          });
        });

        // Determine grouped task IDs
        const groupedTaskIds = new Set<number>();
        Object.values(backendGroups).forEach(g =>
          (g.taskIds || []).forEach(tid => groupedTaskIds.add(tid))
        );

        // Build group parent rows with nested children
        const groupRows: GanttTaskRow[] = Object.entries(backendGroups)
          .map(([gId, g]): GanttTaskRow | null => {
            const children = (g.taskIds || [])
              .map(tid => taskById.get(tid))
              .filter((t): t is GanttTaskRow => !!t && !isNaN(t.start.getTime()) && !isNaN(t.end.getTime()));
            if (children.length === 0) return null;
            const minStart = new Date(Math.min(...children.map(t => t.start.getTime())));
            const maxEnd = new Date(Math.max(...children.map(t => t.end.getTime())));
            return {
              id: `group_${gId}`,
              start: minStart,
              end: maxEnd,
              title: g.groupName || `Group ${gId}`,
              percentComplete: 0,
              isRollup: true,
              isExpanded: true,
              taskDuration: null,
              taskDescription: "",
              color: g.color || "#a0aec0",
              _isGroup: true,
              children,
            };
          })
          .filter((r): r is GanttTaskRow => r !== null);

        // Ungrouped tasks
        const ungroupedTasks = Array.from(taskById.values())
          .filter(t => !groupedTaskIds.has(t.id as number) && !isNaN(t.start.getTime()) && !isNaN(t.end.getTime()));

        const combined = [...groupRows, ...ungroupedTasks].sort(
          (a, b) => a.start.getTime() - b.start.getTime()
        );

        // Build flat list for CSS/tooltip
        const flat: GanttTaskRow[] = [];
        const flatten = (items: GanttTaskRow[]) => items.forEach(t => {
          flat.push(t);
          if (t.children?.length) flatten(t.children);
        });
        flatten(combined);

        setScheduleData(combined);
        setAllTasksFlat(flat);

        // Dependencies (only between real tasks)
        const formattedDependencies = Array.from(taskById.values())
          .filter(t => t.rawPredecessor && t.rawPredecessor !== "none" && t.rawPredecessor !== "" && t.rawPredecessor !== "-1")
          .map((t, index) => {
            const fromId = Number(t.rawPredecessor);
            if (isNaN(fromId)) return null;
            return {
              id: index + 1000,
              fromId,
              toId: t.id,
              type: t.rawDepType !== undefined && t.rawDepType !== -1 ? t.rawDepType : 1,
            };
          })
          .filter((d): d is { id: number; fromId: number; toId: number | string; type: number } => d !== null);

        setDependencyData(formattedDependencies);
      } catch (error) {
        console.error("Error fetching schedule data for Gantt:", error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [projectIdentifier]);

  const handleTaskClick = (event: GanttTaskClickEvent) => {
    if (onTaskSelect && event.dataItem && !event.dataItem._isGroup) {
      onTaskSelect(event.dataItem.id);
    }
  };

  const handleExpandChange = (e: GanttExpandChangeEvent) => {
    const id = String(e.dataItem?.id);
    setScheduleData(prev => prev.map(row =>
      String(row.id) === id ? { ...row, isExpanded: !row.isExpanded } : row
    ));
  };

  const colorCss = useMemo(() =>
    allTasksFlat
      .map(t => `[data-task-id="${t.id}"].k-task-single,[data-task-id="${t.id}"].k-task-milestone{background-color:${t.color}!important;border-color:${t.color}!important;}`)
      .join(""),
    [allTasksFlat]);

  if (loading) {
    return (
      <div className="flex justify-center items-center border rounded-md h-[400px] text-gray-500">
        Loading Chart...
      </div>
    );
  }

  if (scheduleData.length === 0) {
    return (
      <div className="flex justify-center items-center border rounded-md h-[400px] text-gray-500">
        No tasks to show. Click <strong className="mx-1">Add Schedule</strong> to add tasks.
      </div>
    );
  }

  return (
    <div className="w-full h-full flex flex-col">
      <div
        className="gantt-no-subheader w-full h-full overflow-x-auto border rounded-md relative"
        style={{ minHeight: "420px" }}
        onMouseMove={handleGanttMouseMove}
        onMouseOver={handleGanttMouseOver}
        onMouseLeave={() => setTooltipTask(null)}
      >
        <style>{`.gantt-no-subheader .k-gantt-header tr:nth-child(2){display:none!important}${colorCss}`}</style>
        <Gantt
          style={{ height: "100%", width: "100%", minHeight: "420px" }}
          taskData={scheduleData}
          taskModelFields={taskModelFields}
          dependencyData={dependencyData}
          dependencyModelFields={dependencyModelFields}
          columns={columns}
          onTaskClick={handleTaskClick}
          onExpandChange={handleExpandChange}
        >
          <GanttWeekView />
          <GanttMonthView timelineHeaderCell={MonthViewHeaderCell} />
        </Gantt>
        {tooltipTask && (
          <div
            className="fixed z-[9999] pointer-events-none bg-background border border-border rounded-md shadow-lg px-3 py-2 min-w-[160px]"
            style={{ left: tooltipPos.x, top: tooltipPos.y - 8, transform: "translate(-50%, -100%)" }}
          >
            <div className="text-xs font-semibold text-foreground mb-1">{tooltipTask.title}</div>
            <div className="text-xs text-muted-foreground">Start: {formatDate(format(tooltipTask.start, "yyyy-MM-dd"))}</div>
            <div className="text-xs text-muted-foreground">End: {formatDate(format(tooltipTask.end, "yyyy-MM-dd"))}</div>
            <div className="text-xs text-muted-foreground">Duration: {tooltipTask.taskDuration != null ? `${tooltipTask.taskDuration} M` : "—"}</div>
          </div>
        )}
      </div>
    </div>
  );
};

export default ScheduleGanttShowComponent;
