"use client";
import {
  addMonths,
  differenceInDays,
  differenceInMonths,
  format,
  parseISO,
  subMonths,
  addDays,
  subDays,
  isValid,
  isBefore,
  startOfToday,
} from "date-fns";
import { useState } from "react";

// --- Pure Calculation Functions ---

/**
 * Calculates End Date based on Start Date and Duration (Months).
 * Logic: End Date = (Start Date + Duration) - 1 Day.
 */
export const calculateTaskEndDate = (
  startDate: string,
  duration: number
): string => {
  if (!startDate || isNaN(duration)) return "";
  const taskStart = parseISO(startDate);
  if (!isValid(taskStart)) return "";

  const wholeMonths = Math.floor(duration);
  const fractionalMonths = duration % 1;
  const fractionalDays = Math.round(fractionalMonths * 30);

  let tempDate = addMonths(taskStart, wholeMonths);
  tempDate = addDays(tempDate, fractionalDays);
  const taskEnd = subDays(tempDate, 1); // Inclusive logic

  return isValid(taskEnd) ? format(taskEnd, "yyyy-MM-dd") : "";
};

/**
 * Calculates Start Date based on End Date and Duration.
 * Logic: Start Date = (End Date + 1 Day) - Duration.
 */
export const calculateTaskStartDate = (
  endDate: string,
  duration: number
): string => {
  if (!endDate || isNaN(duration)) return "";
  const taskEnd = parseISO(endDate);
  if (!isValid(taskEnd)) return "";

  const wholeMonths = Math.floor(duration);
  const fractionalMonths = duration % 1;
  const fractionalDays = Math.round(fractionalMonths * 30);

  let tempDate = addDays(taskEnd, 1);
  tempDate = subDays(tempDate, fractionalDays);
  const taskStart = subMonths(tempDate, wholeMonths);

  return isValid(taskStart) ? format(taskStart, "yyyy-MM-dd") : "";
};

/**
 * Calculates Duration based on Start and End dates.
 */
export const calculateTaskDuration = (
  startDate: string,
  endDate: string
): number => {
  if (!startDate || !endDate) return 0;

  const taskStart = parseISO(startDate);
  const taskEnd = parseISO(endDate);

  if (!isValid(taskStart) || !isValid(taskEnd)) return 0;
  if (isBefore(taskEnd, taskStart)) return 0;

  const exclusiveEnd = addDays(taskEnd, 1);
  const months = differenceInMonths(exclusiveEnd, taskStart);
  const tempDateAfterMonths = addMonths(taskStart, months);
  const days = differenceInDays(exclusiveEnd, tempDateAfterMonths);

  const duration = months + days / 30;
  return parseFloat(duration.toFixed(2));
};

// --- Cascading Updates & Dependency Logic ---

export const calculateDependentDates = (
  predStart: string,
  predEnd: string,
  dependencyType: string,
  lag: number,
  duration: number
): { startDate: string; endDate: string } | null => {
  if (!predStart || !predEnd) return null;

  const pStart = parseISO(predStart);
  const pEnd = parseISO(predEnd);

  if (!isValid(pStart) || !isValid(pEnd)) return null;

  const lagDays = Math.round((lag || 0) * 30);

  if (dependencyType === "1") {
    // Finish-to-Start
    const newStart = addDays(pEnd, 1 + lagDays);
    const startDateStr = format(newStart, "yyyy-MM-dd");
    const endDateStr = calculateTaskEndDate(startDateStr, duration);
    return { startDate: startDateStr, endDate: endDateStr };
  } else if (dependencyType === "3") {
    // Start-to-Start
    const newStart = addDays(pStart, lagDays);
    const startDateStr = format(newStart, "yyyy-MM-dd");
    const endDateStr = calculateTaskEndDate(startDateStr, duration);
    return { startDate: startDateStr, endDate: endDateStr };
  } else if (dependencyType === "0") {
    // Finish-to-Finish
    const newEnd = addDays(pEnd, lagDays);
    const endDateStr = format(newEnd, "yyyy-MM-dd");
    const startDateStr = calculateTaskStartDate(endDateStr, duration);
    return { startDate: startDateStr, endDate: endDateStr };
  }

  return null;
};

/**
 * Recursively updates dependent tasks in the list.
 */
export const recalculateCascadingDates = (
  allTasks: any[],
  rootTaskId: number
): any[] => {
  const tasksMap = new Map(allTasks.map((t) => [t.id, { ...t }]));

  const processTask = (parentId: number) => {
    const parent = tasksMap.get(parentId);
    if (!parent) return;

    const children = Array.from(tasksMap.values()).filter(
      (t) => String(t.taskPredecessor) === String(parentId)
    );

    children.forEach((child) => {
      const depType = String(child.dependencyType || "1");
      const lag = child.delayDuration || 0;
      const duration = child.taskDuration || 0;

      const newDates = calculateDependentDates(
        parent.taskStart,
        parent.taskEnd,
        depType,
        lag,
        duration
      );

      if (newDates) {
        const updatedChild = {
          ...child,
          taskStart: newDates.startDate,
          taskEnd: newDates.endDate,
        };
        tasksMap.set(child.id, updatedChild);
        processTask(child.id);
      }
    });
  };

  processTask(rootTaskId);
  return Array.from(tasksMap.values());
};

// --- Recursive Deletion Helper ---

export const getRecursiveChildIds = (
  taskId: number,
  allTasks: any[]
): number[] => {
  let idsToDelete: number[] = [taskId];
  const children = allTasks.filter(
    (t) => t.taskPredecessor && String(t.taskPredecessor) === String(taskId)
  );

  for (const child of children) {
    const childIds = getRecursiveChildIds(child.id, allTasks);
    idsToDelete = [...idsToDelete, ...childIds];
  }
  return Array.from(new Set(idsToDelete));
};

// --- Validation Logic ---

export type ValidationResult = { isValid: boolean; message?: string };

export const validateTaskDeletion = (taskStartDate: string): ValidationResult => {
  const start = parseISO(taskStartDate);
  const today = startOfToday();
  if (isBefore(start, today)) {
    return { isValid: false, message: "You can only delete future tasks." };
  }
  return { isValid: true };
};

export const validateTaskForm = (
  formData: any,
  existingTasks: any[],
  currentTaskId: number | null
): ValidationResult => {
  if (!formData.taskName?.trim()) {
    return { isValid: false, message: "Please enter the Schedule Name" };
  }

  const isDuplicate = existingTasks.some(
    (t) =>
      t.taskName === formData.taskName &&
      String(t.id) !== String(currentTaskId || "")
  );
  if (isDuplicate) {
    return { isValid: false, message: "This task name already exists" };
  }

  if (formData.duration < 0) {
    return { isValid: false, message: "Task Duration cannot be negative." };
  }

  if (
    formData.predecessor &&
    formData.predecessor !== "-1" &&
    (!formData.dependencyType || formData.dependencyType === "-1")
  ) {
    return { isValid: false, message: "Please select dependency type" };
  }

  return { isValid: true };
};

// --- Custom Hook ---

export const useScheduleDateLogic = () => {
  const [startDate, setStartDate] = useState("");
  const [endDate, setEndDate] = useState("");
  const [duration, setDuration] = useState(0);

  const setValuesRaw = (s: string, e: string, d: number) => {
    setStartDate(s);
    setEndDate(e);
    setDuration(d);
  };

  const handleStartDateChange = (value: string) => {
    setStartDate(value);
    if (value) {
      const updatedEndDate = calculateTaskEndDate(value, duration);
      setEndDate(updatedEndDate);
    }
  };

  const handleEndDateChange = (value: string) => {
    setEndDate(value);
    if (startDate && value) {
      if (isBefore(parseISO(value), parseISO(startDate))) {
        return;
      }
      const updatedDuration = calculateTaskDuration(startDate, value);
      setDuration(Math.max(0, updatedDuration));
    }
  };

  const handleDurationChange = (value: number) => {
    setDuration(value);
    if (startDate) {
      const updatedEndDate = calculateTaskEndDate(startDate, value);
      setEndDate(updatedEndDate);
    }
  };

  const resetDates = () => {
    setStartDate("");
    setEndDate("");
    setDuration(0);
  };

  return {
    startDate,
    endDate,
    duration,
    handleStartDateChange,
    handleEndDateChange,
    handleDurationChange,
    resetDates,
    setValuesRaw,
  };
};
