import {useReactFlow, useStoreApi} from "@xyflow/react";
import clsx from "clsx";
import {useEffect, useState} from "react";
import useFlowStore from "../VisProgStores.tsx";
import {
  warningSummary,
  type WarningSeverity,
  type EditorWarning, globalWarning
} from "./EditorWarnings.tsx";
import styles from "./WarningSidebar.module.css";

export function WarningsSidebar() {
  const warnings = useFlowStore.getState().getWarnings();

  const [severityFilter, setSeverityFilter] = useState<WarningSeverity | 'ALL'>('ALL');

  useEffect(() => {}, [warnings]);
  const filtered = severityFilter === 'ALL'
    ? warnings
    : warnings.filter(w => w.severity === severityFilter);




  return (
    <aside className={styles.warningsSidebar}>
      <WarningsHeader
        severityFilter={severityFilter}
        onChange={setSeverityFilter}
      />

      <WarningsList warnings={filtered} />
    </aside>
  );
}

function WarningsHeader({
  severityFilter,
  onChange,
}: {
  severityFilter: WarningSeverity | 'ALL';
  onChange: (severity: WarningSeverity | 'ALL') => void;
}) {
  const summary = warningSummary();

  return (
    <div className={styles.warningsHeader}>
      <h3>Warnings</h3>

      <div className={styles.severityTabs}>
        {(['ALL', 'ERROR', 'WARNING', 'INFO'] as const).map(severity => (
          <button
            key={severity}
            className={clsx(styles.severityTab, severityFilter === severity && styles.active)}
            onClick={() => onChange(severity)}
          >
            {severity}
            {severity !== 'ALL' && (
              <span className={styles.count}>
                {summary[severity.toLowerCase() as keyof typeof summary]}
              </span>
            )}
          </button>
        ))}
      </div>
    </div>
  );
}



function WarningsList(props: { warnings: EditorWarning[] }) {
  const splitWarnings = {
    global: props.warnings.filter(w => w.scope.id === globalWarning),
    other: props.warnings.filter(w => w.scope.id !== globalWarning),
  }

  if (props.warnings.length === 0) {
    return (
      <div className={styles.warningsEmpty}>
        No warnings!
      </div>
    )
  }
  if (splitWarnings.global.length === 0) {
    return (
      <div>
        <div className={"warningGroup"}>
          <div className={styles.warningGroupHeader}>global:</div>
          <div className={styles.warningsEmpty}>
            No global warnings!
          </div>
        </div>
        <div className={"warningGroup"}>
          <div className={styles.warningGroupHeader}>other:</div>
          <div className={styles.warningsList}>
            {splitWarnings.other.map((warning) => (
              <WarningListItem warning={warning} />
            ))}
          </div>
        </div>
      </div>
    );
  }
  return (
    <div>
      <div className={"warningGroup"}>
        <div className={styles.warningGroupHeader}>global:</div>
        <div className={styles.warningsList}>
          {splitWarnings.global.map((warning) => (
            <WarningListItem warning={warning} />
          ))}
        </div>
      </div>
      <div className={"warningGroup"}>
        <div className={styles.warningGroupHeader}>other:</div>
        <div className={styles.warningsList}>
          {splitWarnings.other.map((warning) => (
            <WarningListItem warning={warning} />
          ))}
        </div>
      </div>
    </div>
  );
}

function WarningListItem(props: { warning: EditorWarning }) {
  const jumpToNode = useJumpToNode();

  return (
    <div
      className={clsx(styles.warningItem, styles[`warning-item--${props.warning.severity.toLowerCase()}`],)}
      onClick={() => jumpToNode(props.warning.scope.id)}
    >
      <div className={styles.description}>
        {props.warning.description}
      </div>

      <div className={styles.meta}>
        {props.warning.scope.id}
        {props.warning.scope.handleId && (
          <span className={styles.handle}>@{props.warning.scope.handleId}</span>
        )}
      </div>
    </div>
  );
}

function useJumpToNode() {
  const { getNode, setCenter } = useReactFlow();
  const { addSelectedNodes } = useStoreApi().getState();

  return (nodeId: string) => {
    // user can't jump to global warning, so prevent further logic from running
    if (nodeId === globalWarning) return;
    const node = getNode(nodeId);
    if (!node) return;

    const { position, width = 0, height = 0} = node;

    // move to node
    setCenter(
      position!.x + width / 2,
      position!.y + height / 2,
      { zoom: 2, duration: 300 }
    ).then(() => {
      // select the node
      addSelectedNodes([nodeId]);
    });

  };
}