import React, { createContext, useCallback, useContext, useMemo, useState } from "react";

import { Alert, Button, Snackbar } from "@mui/material";

type Severity = "success" | "info" | "warning" | "error";

type Toast = {
  open: boolean;
  message: string;
  severity: Severity;
  actionLabel?: string;
  onAction?: () => void;
};

type ToastApi = {
  toast: (
    message: string,
    severity?: Severity,
    action?: { label: string; onClick: () => void },
  ) => void;
};

const ToastContext = createContext<ToastApi | null>(null);

export function ToastProvider({ children }: { children: React.ReactNode }) {
  const [t, setT] = useState<Toast>({ open: false, message: "", severity: "info" });

  const toast = useCallback(
    (message: string, severity: Severity = "info", action?: { label: string; onClick: () => void }) => {
      setT({
        open: true,
        message,
        severity,
        actionLabel: action?.label,
        onAction: action?.onClick,
      });
    },
    [],
  );

  const value = useMemo(() => ({ toast }), [toast]);

  return (
    <ToastContext.Provider value={value}>
      {children}
      <Snackbar
        open={t.open}
        autoHideDuration={3500}
        onClose={() => setT((p) => ({ ...p, open: false }))}
        anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
      >
        <Alert
          onClose={() => setT((p) => ({ ...p, open: false }))}
          severity={t.severity}
          variant="filled"
          sx={{ maxWidth: 420 }}
          action={
            t.actionLabel && t.onAction ? (
              <Button
                color="inherit"
                size="small"
                onClick={() => {
                  setT((p) => ({ ...p, open: false }));
                  t.onAction?.();
                }}
              >
                {t.actionLabel}
              </Button>
            ) : undefined
          }
        >
          {t.message}
        </Alert>
      </Snackbar>
    </ToastContext.Provider>
  );
}

export function useToast(): ToastApi {
  const v = useContext(ToastContext);
  if (!v) throw new Error("useToast must be used within ToastProvider");
  return v;
}
