import {
  useEffect,
  useState,
  type ReactNode
} from "react";
import { Link } from "react-router";
import { adminErrorMessage } from "./admin/adminUtils";

export type DashboardWidgetDataState<T> = {
  data: T | null;
  loading: boolean;
  error: string;
};

export function useDashboardWidgetData<T>(
  load: () => Promise<T>,
  refreshKey: number
): DashboardWidgetDataState<T> {
  const [state, setState] = useState<DashboardWidgetDataState<T>>({
    data: null,
    loading: true,
    error: ""
  });

  useEffect(() => {
    let active = true;
    setState((current) => ({
      ...current,
      loading: true,
      error: ""
    }));
    void load()
      .then((data) => {
        if (active) setState({ data, loading: false, error: "" });
      })
      .catch((error: unknown) => {
        if (!active) return;
        setState((current) => ({
          ...current,
          loading: false,
          error: adminErrorMessage(error)
        }));
      });
    return () => {
      active = false;
    };
  }, [load, refreshKey]);

  return state;
}

export type DashboardWidgetListItem = {
  id: string;
  title: ReactNode;
  detail?: ReactNode;
  meta?: ReactNode;
  leading?: ReactNode;
  trailing?: ReactNode;
  to?: string;
};

export function DashboardWidgetList({
  items,
  emptyText
}: {
  items: DashboardWidgetListItem[];
  emptyText: ReactNode;
}) {
  if (!items.length) {
    return <p className="muted dashboard-contribution-empty">{emptyText}</p>;
  }

  return (
    <ul className="dashboard-contribution-list">
      {items.map((item) => {
        const content = (
          <>
            {item.leading && (
              <span className="dashboard-contribution-leading">
                {item.leading}
              </span>
            )}
            <span className="dashboard-contribution-copy">
              <span className="dashboard-contribution-title">
                {item.title}
              </span>
              {item.detail && (
                <span className="dashboard-contribution-detail">
                  {item.detail}
                </span>
              )}
            </span>
            {item.meta && (
              <span className="dashboard-contribution-meta">
                {item.meta}
              </span>
            )}
            {item.trailing && (
              <span className="dashboard-contribution-trailing">
                {item.trailing}
              </span>
            )}
          </>
        );
        return (
          <li key={item.id}>
            {item.to ? (
              <Link className="dashboard-contribution-row" to={item.to}>
                {content}
              </Link>
            ) : (
              <div className="dashboard-contribution-row">{content}</div>
            )}
          </li>
        );
      })}
    </ul>
  );
}
