import { useCallback } from "react";
import { Waypoints } from "lucide-react";
import { Link } from "react-router-dom";
import {
  DashboardWidgetList,
  DismissibleAlert,
  LoadingFrame,
  StatusBadge,
  useDashboardWidgetData,
  type ApiSettings,
  type DashboardWidgetConfiguration
} from "@govoplan/core-webui";
import {
  listDataflowPipelines,
  type Pipeline
} from "../../api/dataflow";

export default function DataflowPipelinesWidget({
  settings,
  refreshKey,
  configuration
}: {
  settings: ApiSettings;
  refreshKey: number;
  configuration: DashboardWidgetConfiguration;
}) {
  const maxItems = numberSetting(configuration.maxItems, 5, 1, 12);
  const includeDrafts = configuration.includeDrafts !== false;
  const load = useCallback(async () => {
    const pipelines = await listDataflowPipelines(settings);
    return pipelines
      .filter((pipeline) => includeDrafts || pipeline.status !== "draft")
      .sort(comparePipelines)
      .slice(0, maxItems);
  }, [includeDrafts, maxItems, settings]);
  const { data: pipelines, loading, error } = useDashboardWidgetData(
    load,
    refreshKey
  );

  return (
    <LoadingFrame loading={loading} label="Loading dataflows">
      {error && (
        <DismissibleAlert tone="warning" resetKey={error}>
          {error}
        </DismissibleAlert>
      )}
      <DashboardWidgetList
        emptyText="No dataflows are available."
        items={(pipelines ?? []).map((pipeline) => ({
          id: pipeline.id,
          title: pipeline.name,
          detail: pipelineDescription(pipeline),
          meta: scopeLabel(pipeline),
          leading: <Waypoints size={17} aria-hidden="true" />,
          trailing: (
            <StatusBadge status={pipeline.status} label={pipeline.status} />
          ),
          to: "/dataflow"
        }))}
      />
      <div className="dashboard-contribution-footer">
        <Link className="btn btn-secondary" to="/dataflow">
          Open dataflow
        </Link>
      </div>
    </LoadingFrame>
  );
}

function comparePipelines(left: Pipeline, right: Pipeline): number {
  if (left.status !== right.status) {
    if (left.status === "active") return -1;
    if (right.status === "active") return 1;
  }
  return (
    new Date(right.updated_at).getTime() - new Date(left.updated_at).getTime()
  );
}

function pipelineDescription(pipeline: Pipeline): string {
  const nodeCount = pipeline.revision.graph.nodes.length;
  const kind =
    pipeline.governance.definition_kind === "template" ? "template" : "flow";
  return `${nodeCount} ${nodeCount === 1 ? "node" : "nodes"} · ${kind}`;
}

function scopeLabel(pipeline: Pipeline): string {
  const scope = pipeline.governance.scope_type;
  return scope.charAt(0).toUpperCase() + scope.slice(1);
}

function numberSetting(
  value: unknown,
  fallback: number,
  minimum: number,
  maximum: number
): number {
  const numeric = typeof value === "number" ? value : Number(value);
  return Number.isFinite(numeric)
    ? Math.max(minimum, Math.min(maximum, Math.floor(numeric)))
    : fallback;
}
