import type {
  QueueTaskItem as TQueueTaskItem,
  QueueTaskItemStatus,
  ViewPatchMessage,
} from "@codeflash/types";
import { vscode } from "../utils/vscode";
import { useEffect, useMemo, useRef, useState } from "react";
import styles from "../styles/optimizationQueue.module.css";
import {
  canDeleteTaskInQueue,
  canRetryTaskInQueue,
  getFileNameFromPath,
  isOutsideModuleRoot,
  isTaskRunning,
} from "@codeflash/shared";
import { useStore } from "../store/root";
import Tooltip from "./tooltip";

const OptimizationQueue = ({
  queueTasks,
}: {
  queueTasks: TQueueTaskItem[];
}) => {
  const sortedTasks = useMemo(() => {
    const statusPriority: Record<QueueTaskItemStatus, number> = {
      initializing: 1,
      optimizing: 2,
      completed: 3,
      queued: 4,
      rejected: 5,
      canceled: 6,
      failed: 7,
      skipped: 8,
    };

    return queueTasks.slice().sort((a, b) => {
      const aPriority = statusPriority[a.status] || 999;
      const bPriority = statusPriority[b.status] || 999;
      if (aPriority !== bPriority) {
        return aPriority - bPriority;
      }
      return b.id.localeCompare(a.id);
    });
  }, [queueTasks]);

  return (
    <div className={styles.queueTasks}>
      <div className={styles.queueTasksHeader} id="queue-tasks-toggle">
        <div className={styles.queueTasksTitle}>
          <span className={`${styles.queueTasksChevron}`}></span>
          <span>⚡ Optimizations</span>
        </div>
      </div>

      <div
        className={`${styles.queueTasksContent} ${styles.expanded}`}
        id="queue-tasks-content"
      >
        <ul id="queue-tasks-list" className={styles.queueTasksList}>
          {sortedTasks.length === 0 ? (
            <li className={styles.queueEmptyState}>
              <div className={styles.queueEmptyContent}>
                <span className="codicon codicon-rocket"></span>
                <span>No optimizations yet</span>
                <small className={styles.queueEmptyHint}>
                  Add functions to the queue by clicking the small{" "}
                  <b>optimize</b> button above a function
                </small>
              </div>
            </li>
          ) : (
            sortedTasks.map((task) => (
              <QueueTaskItem key={task.id} task={task} />
            ))
          )}
        </ul>
      </div>
    </div>
  );
};

export const Options = () => {
  const [optionsOpen, setOptionsOpen] = useState(false);
  const optionsButtonRef = useRef<HTMLButtonElement | null>(null);
  const dropdownRef = useRef<HTMLDivElement | null>(null);
  const setActiveTab = useStore((state) => state.setActiveTab);
  const currentFilePath = useStore((state) => state.currentFilePath);
  const [currentFileInsideModuleRoot, setCurrentFileInsideModuleRoot] =
    useState(false);
  const moduleRoot = useStore((state) => state.moduleRoot);

  useEffect(() => {
    if (!currentFilePath) {
      setCurrentFileInsideModuleRoot(false);
      return;
    }
    const isOutside = isOutsideModuleRoot(moduleRoot, currentFilePath);
    setCurrentFileInsideModuleRoot(!isOutside);
  }, [currentFilePath, moduleRoot]);

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (
        dropdownRef.current &&
        !dropdownRef.current.contains(event.target as Node) &&
        optionsButtonRef.current &&
        !optionsButtonRef.current.contains(event.target as Node)
      ) {
        setOptionsOpen(false);
      }
    }

    if (optionsOpen) {
      document.addEventListener("mousedown", handleClickOutside);
    }

    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [optionsOpen]);
  return (
    <div style={{ position: "relative" }}>
      <button
        id="options-dropdown"
        title="More options"
        ref={optionsButtonRef}
        className={styles.actionButton}
        onClick={() => setOptionsOpen((prev) => !prev)}
        role="button"
        type="button"
      >
        <span className="codicon codicon-kebab-vertical"></span>
      </button>
      {optionsOpen && (
        <div className={styles.options} ref={dropdownRef}>
          <span
            onClick={(e) => {
              e.stopPropagation();
              vscode.postMessage({
                type: "viewLogs",
              });
              setOptionsOpen(false);
            }}
          >
            View Codeflash logs
          </span>
          <Tooltip
            content={
              !currentFilePath
                ? "No file is currently open"
                : currentFileInsideModuleRoot
                  ? `Add all optimizable functions from ${getFileNameFromPath(currentFilePath)} to the queue`
                  : `${getFileNameFromPath(currentFilePath)} is outside the module root`
            }
            position="bottom"
          >
            <span
              onClick={(e) => {
                e.stopPropagation();
                if (!currentFilePath || !currentFileInsideModuleRoot) {
                  return;
                }
                vscode.postMessage({ type: "optimizeCurrentFile" });
                setOptionsOpen(false);
              }}
              className={
                currentFilePath && currentFileInsideModuleRoot
                  ? ""
                  : styles.disabled
              }
            >
              Optimize current file
            </span>
          </Tooltip>
          <span
            onClick={(e) => {
              e.stopPropagation();
              vscode.postMessage({ type: "optimizeCurrentDiff" });
              setOptionsOpen(false);
            }}
            title="Find and optimize functions in your git diff"
          >
            Optimize modified code
          </span>
          <span
            onClick={(e) => {
              e.stopPropagation();
              setActiveTab("projectConfig");
              setOptionsOpen(false);
            }}
          >
            Project Config
          </span>
        </div>
      )}
    </div>
  );
};

const renderMultilineText = (text: string) => {
  const lines = text.split("\n");
  return lines.map((line, index, array) => (
    <span key={index}>
      {line}
      {index < array.length - 1 && <br />}
    </span>
  ));
};

const QueueTaskItem = ({ task }: { task: TQueueTaskItem }) => {
  return (
    <li className={styles.queueTaskItem + " " + styles[task.status]}>
      <div>
        <span className={styles.queueTaskName}>
          <div className={styles.taskItemHeader}>
            <TaskStatus task={task} />
          </div>

          <div className={styles.taskItemLabel}>
            <span
              className={styles.functionName}
              title={task.filepath}
              onClick={() => {
                vscode.postMessage({
                  type: "navigateToFunction",
                  payload: {
                    functionName: task.functionName || "",
                    filePath: task.filepath || "",
                  },
                });
              }}
            >
              {task.functionName}
            </span>
          </div>
        </span>

        {task.description && (
          <div className={styles.queueTaskDescription}>
            {renderMultilineText(task.description)}
          </div>
        )}

        {/* {task.error && (
          <div className={styles.queueTaskError}>{task.error}</div>
        )} */}
      </div>
      {/* ACTIONS */}
      <TaskAction task={task} />
    </li>
  );
};

const alternativeStatusNames: Partial<Record<QueueTaskItemStatus, string>> = {
  skipped: "No optimization found",
};

const TaskStatus = ({ task }: { task: TQueueTaskItem }) => {
  const statusName = alternativeStatusNames[task.status] || task.status;
  switch (task.status) {
    case "optimizing":
    case "initializing":
      return (
        <span className={styles.queueTaskStatus + " " + styles[task.status]}>
          <span className="codicon codicon-sync spin" />
          <span>{statusName}</span>
        </span>
      );
    case "queued":
      return (
        <span className={styles.queueTaskStatus + " " + styles.queued}>
          <span className="codicon codicon-clock" />
          <span>{statusName}</span>
        </span>
      );
    case "failed":
      return (
        <span className={styles.queueTaskStatus + " " + styles.failed}>
          <span className="codicon codicon-error" />
          <span>{statusName}</span>
        </span>
      );
    case "completed":
      return (
        <span className={styles.queueTaskStatus + " " + styles.completed}>
          <span className="codicon codicon-pass-filled" />
          <span>
            {statusName} ({task.speedupStr})
          </span>
        </span>
      );
    case "canceled":
      return (
        <span className={styles.queueTaskStatus + " " + styles.skipped}>
          <span className="codicon codicon-circle-slash" />
          <span>{statusName}</span>
        </span>
      );
    case "skipped":
      return (
        <span className={styles.queueTaskStatus + " " + styles.skipped}>
          <span className="codicon codicon-warning" />
          <span>{statusName}</span>
        </span>
      );
    case "rejected":
      return (
        <span className={styles.queueTaskStatus + " " + styles.rejected}>
          <span className="codicon codicon-x" />
          <span>{statusName}</span>
        </span>
      );
    default:
      return null;
  }
};

const TaskAction = ({ task }: { task: TQueueTaskItem }) => {
  return (
    <div className={styles.queueTaskActions}>
      {canRetryTaskInQueue(task) && (
        <button
          className={styles.ghostActionButton}
          title="Retry"
          onClick={() => {
            vscode.postMessage({
              type: "optimizeFunction",
              payload: {
                functionName: task.functionName || "",
                filePath: task.filepath || "",
              },
            });
          }}
        >
          <span className="codicon codicon-refresh"></span>
        </button>
      )}

      {(isTaskRunning(task) ? true : canDeleteTaskInQueue(task)) && (
        <button
          className={styles.ghostActionButton}
          title={isTaskRunning(task) ? "Stop" : "Remove"}
          onClick={(e) => {
            e.stopPropagation();
            vscode.postMessage({
              type: isTaskRunning(task) ? "cancelTask" : "deleteTask",
              payload: { id: task.id },
            });
          }}
        >
          <span
            className={
              "codicon " +
              (isTaskRunning(task) ? "codicon-debug-stop" : "codicon-trash")
            }
          ></span>{" "}
        </button>
      )}

      {task.status === "completed" && task.patchFile && (
        <button
          className={styles.queueTaskPatch}
          onClick={() => {
            const msg: ViewPatchMessage = {
              type: "viewPatch",
              payload: {
                id: task.id,
                functionName: task.functionName,
                patchFile: task.patchFile!,
                explanation: task.explanation || "",
                speedupStr: task.speedupStr || "",
                optimizationReview: task.optimizationReview || "",
                originalRuntime: task.originalRuntime || 0,
                optimizedRuntime: task.optimizedRuntime || 0,
                originalLineProfiler: task.originalLineProfiler || "",
                optimizedLineProfiler: task.optimizedLineProfiler || "",
              },
            };
            vscode.postMessage(msg);
          }}
        >
          <span className="codicon codicon-eye"></span>
          <span>View Optimization</span>
        </button>
      )}

      {task.prUrl && (
        <button
          className={styles.queueTaskPrLink}
          onClick={() => {
            vscode.postMessage({
              type: "openExternal",
              payload: { url: task.prUrl! },
            });
          }}
          title="Open Pull Request"
        >
          <span className="codicon codicon-git-pull-request"></span>
          <span>View PR</span>
        </button>
      )}
    </div>
  );
};
export default OptimizationQueue;
