import { useCallback } from "react";
import { CalendarClock } from "lucide-react";
import { Link } from "react-router-dom";
import {
  DashboardWidgetList,
  DismissibleAlert,
  LoadingFrame,
  StatusBadge,
  useDashboardWidgetData,
  type ApiSettings,
  type DashboardWidgetConfiguration
} from "@govoplan/core-webui";
import {
  listSchedulingRequests,
  type SchedulingRequest
} from "../../api/scheduling";

export default function SchedulingRequestsWidget({
  settings,
  refreshKey,
  configuration
}: {
  settings: ApiSettings;
  refreshKey: number;
  configuration: DashboardWidgetConfiguration;
}) {
  const maxItems = numberSetting(configuration.maxItems, 5, 1, 12);
  const includeDrafts = configuration.includeDrafts === true;
  const load = useCallback(async () => {
    const response = await listSchedulingRequests(settings);
    return response.requests
      .filter(
        (request) =>
          request.status === "collecting"
          || (includeDrafts && request.status === "draft")
      )
      .sort(compareRequests)
      .slice(0, maxItems);
  }, [includeDrafts, maxItems, settings]);
  const { data: requests, loading, error } = useDashboardWidgetData(
    load,
    refreshKey
  );

  return (
    <LoadingFrame loading={loading} label="Loading scheduling requests">
      {error && (
        <DismissibleAlert tone="warning" resetKey={error}>
          {error}
        </DismissibleAlert>
      )}
      <DashboardWidgetList
        emptyText="No scheduling requests are awaiting responses."
        items={(requests ?? []).map((request) => ({
          id: request.id,
          title: request.title,
          detail: responseLabel(request),
          meta: deadlineLabel(request),
          leading: <CalendarClock size={17} aria-hidden="true" />,
          trailing: (
            <StatusBadge
              status={request.status}
              label={request.status === "collecting" ? "Open" : "Draft"}
            />
          ),
          to: "/scheduling"
        }))}
      />
      <div className="dashboard-contribution-footer">
        <Link className="btn btn-secondary" to="/scheduling">
          Open scheduling
        </Link>
      </div>
    </LoadingFrame>
  );
}

function compareRequests(
  left: SchedulingRequest,
  right: SchedulingRequest
): number {
  if (left.status !== right.status) {
    return left.status === "collecting" ? -1 : 1;
  }
  const leftDeadline = left.deadline_at
    ? new Date(left.deadline_at).getTime()
    : Number.POSITIVE_INFINITY;
  const rightDeadline = right.deadline_at
    ? new Date(right.deadline_at).getTime()
    : Number.POSITIVE_INFINITY;
  return (
    leftDeadline - rightDeadline
    || new Date(right.updated_at).getTime() - new Date(left.updated_at).getTime()
  );
}

function responseLabel(request: SchedulingRequest): string {
  const responded = request.participant_aggregate.status_counts.responded ?? 0;
  return `${responded} of ${request.participant_aggregate.total} responded`;
}

function deadlineLabel(request: SchedulingRequest): string {
  if (!request.deadline_at) return `${request.slots.length} options`;
  return `Due ${new Intl.DateTimeFormat(undefined, {
    day: "2-digit",
    month: "short"
  }).format(new Date(request.deadline_at))}`;
}

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;
}
