import React, { useEffect, useState, useCallback } from "react";
import templateVersionsService, {
  CreateWorkflowTemplateVersion,
  TaskDefinition,
  TaskMetadata,
} from "../services/WorkflowTemplateService";
import TaskList from "./TaskList";
import { TaskEditor } from "./TasksEditor";

interface TasksTabProps {
  data: CreateWorkflowTemplateVersion;
  errors: Record<string, string>;
  isEditMode: boolean;
  onTasksChange: (name: string, value: TaskDefinition[]) => void;
  onValidate: (taskId: string, isValid: boolean) => void;
  taskValidation: Record<string, boolean>;
}

const TasksTab: React.FC<TasksTabProps> = ({
  data,
  errors,
  isEditMode,
  onTasksChange,
  onValidate,
  taskValidation,
}) => {
  const tasks = data.tasks;
  const [selectedTask, setSelectedTask] = useState<TaskDefinition | null>(null);
  const [pendingSelectGuid, setPendingSelectGuid] = useState<string | null>(
    null,
  );

  useEffect(() => {
    // If we have a pending task GUID to select, find it and select it
    if (pendingSelectGuid) {
      const { task: foundTask } = findTaskAndSiblings(
        pendingSelectGuid,
        tasks,
        null,
      );
      if (foundTask) {
        setSelectedTask(foundTask);
        setPendingSelectGuid(null);
      }
      return;
    }

    // Don't override user selection
    if (selectedTask) return;

    if (tasks.length === 0) {
      setSelectedTask(null);
      return;
    }

    // Find first invalid task
    const firstInvalid = tasks.find(
      (t) => taskValidation[t.config.guid as string] === false,
    );

    if (firstInvalid) {
      setSelectedTask(firstInvalid);
      return;
    }

    // Otherwise select first task
    setSelectedTask(tasks[0]);
  }, [tasks, taskValidation, selectedTask, pendingSelectGuid]);

  const handleTasksChange = React.useCallback(
    (newTasks: TaskDefinition[]) => {
      // Update the parent form state
      onTasksChange("tasks", newTasks);
    },
    [onTasksChange],
  );

  const findTaskAndSiblings = (
    targetGuid: string,
    source: TaskDefinition[],
    parent: TaskDefinition | null = null,
  ): {
    task: TaskDefinition | null;
    siblings: TaskDefinition[];
    parent: TaskDefinition | null;
  } => {
    for (const task of source) {
      if (task.config.guid === targetGuid) {
        return { task, siblings: source, parent };
      }

      const childTasks = (task.config.tasks as TaskDefinition[]) ?? [];
      if (childTasks.length === 0) continue;

      const result = findTaskAndSiblings(targetGuid, childTasks, task);
      if (result.task) {
        return result;
      }
    }

    return { task: null, siblings: [], parent: null };
  };

  const handleTaskEditorChange = React.useCallback(
    (updatedTask: TaskDefinition) => {
      const { siblings } = findTaskAndSiblings(
        updatedTask.config.guid as string,
        tasks,
        null,
      );

      if (siblings.length === 0) {
        return;
      }

      const updateTaskRecursive = (
        source: TaskDefinition[],
      ): TaskDefinition[] => {
        return source.map((t) => {
          if (t.config.guid === updatedTask.config.guid) {
            return updatedTask;
          }

          const childTasks = (t.config.tasks as TaskDefinition[]) ?? [];
          if (childTasks.length === 0) {
            return t;
          }

          const updatedChildren = updateTaskRecursive(childTasks);
          if (updatedChildren === childTasks) {
            return t;
          }

          return {
            ...t,
            config: {
              ...t.config,
              tasks: updatedChildren,
            },
          };
        });
      };

      const newTasks = updateTaskRecursive(tasks);
      handleTasksChange(newTasks);

      // Use the updated object from the array, not the raw updatedTask
      const { task: updatedFromArray } = findTaskAndSiblings(
        updatedTask.config.guid as string,
        newTasks,
      );

      if (updatedFromArray) {
        setSelectedTask(updatedFromArray);
      }
    },
    [tasks, handleTasksChange],
  );

  const handleTaskDelete = React.useCallback(
    (taskId: string) => {
      const removeTaskRecursive = (
        source: TaskDefinition[],
      ): { tasks: TaskDefinition[]; removed: boolean } => {
        let removed = false;

        const updated = source.flatMap((task) => {
          if (task.config.guid === taskId) {
            removed = true;
            return [];
          }

          const childTasks = (task.config.tasks as TaskDefinition[]) ?? [];
          if (childTasks.length === 0) {
            return [task];
          }

          const childResult = removeTaskRecursive(childTasks);
          if (!childResult.removed) {
            return [task];
          }

          removed = true;

          return [
            {
              ...task,
              config: {
                ...task.config,
                tasks: childResult.tasks,
              },
            },
          ];
        });

        return { tasks: updated, removed };
      };

      const removePredecessorRecursive = (
        source: TaskDefinition[],
      ): TaskDefinition[] => {
        return source.map((task) => {
          const childTasks = (task.config.tasks as TaskDefinition[]) ?? [];
          const updatedChildren =
            childTasks.length > 0
              ? removePredecessorRecursive(childTasks)
              : childTasks;

          const predecessors = task.config.predecessors as string[] | undefined;
          const updatedPredecessors = predecessors
            ? predecessors.filter((d) => d !== taskId)
            : predecessors;

          const childrenChanged = updatedChildren !== childTasks;
          const predecessorsChanged = updatedPredecessors !== predecessors;

          if (!childrenChanged && !predecessorsChanged) {
            return task;
          }

          const updatedConfig = { ...task.config } as Record<string, unknown>;
          if (childrenChanged) {
            updatedConfig.tasks = updatedChildren;
          }
          if (predecessorsChanged) {
            updatedConfig.predecessors = updatedPredecessors;
          }

          return {
            ...task,
            config: updatedConfig,
          };
        });
      };

      const deleteResult = removeTaskRecursive(tasks);
      if (!deleteResult.removed) {
        return;
      }

      const newTasks = removePredecessorRecursive(deleteResult.tasks);

      onValidate(taskId, true); // Clear validation state for deleted task
      setSelectedTask(null);
      handleTasksChange(newTasks);
    },
    [tasks, handleTasksChange],
  );

  return (
    <div className="two-column-grid no-scroll workflow-tasks-grid">
      <div className="fit-content-width workflow-tasks-list-host">
        <TaskList
          tasks={tasks}
          validTasksList={taskValidation}
          onChange={handleTasksChange}
          selectedTask={selectedTask}
          onSelectTask={setSelectedTask}
          onValidate={onValidate}
        />
      </div>
      {selectedTask && (
        <div>
          <TaskEditor
            task={selectedTask}
            tasks={tasks}
            siblingTasks={
              findTaskAndSiblings(
                selectedTask.config.guid as string,
                tasks,
                null,
              ).siblings
            }
            parentTask={
              findTaskAndSiblings(
                selectedTask.config.guid as string,
                tasks,
                null,
              ).parent
            }
            onChange={handleTaskEditorChange}
            onValidate={onValidate}
            onDelete={handleTaskDelete}
            onTaskAdded={(taskGuid: string) => {
              setPendingSelectGuid(taskGuid);
            }}
          />
        </div>
      )}
    </div>
  );
};

export default TasksTab;
