import { createContext, useCallback, useContext, useState, type ReactNode } from "react";
import { useTranslation } from "react-i18next";
import Modal from "./Modal";

// App-styled, promise-based replacement for window.confirm. Wrap the tree in
// <ConfirmProvider> once, then anywhere:  const confirm = useConfirm();
//   if (await confirm({ message: "…", danger: true })) { … }
//
// For a decision with more than two outcomes use `useChoice()` instead — never chain two
// confirms, because the second dialog's Cancel/Escape/backdrop is then indistinguishable from
// a deliberate answer (the playlist delete used to read a dismissal as "delete here only" and
// went ahead and deleted).
interface ConfirmOptions {
  title?: string;
  message: ReactNode;
  confirmLabel?: string;
  cancelLabel?: string;
  danger?: boolean;
}

interface Choice {
  id: string;
  label: string;
  danger?: boolean;
}

export interface ChoiceOptions {
  title?: string;
  message: ReactNode;
  cancelLabel?: string;
  /** Rendered left→right after Cancel. Resolves to the clicked choice's `id`. */
  choices: Choice[];
}

type ChoiceFn = (opts: ChoiceOptions) => Promise<string | null>;
type ConfirmFn = (opts: ConfirmOptions) => Promise<boolean>;

const ChoiceContext = createContext<ChoiceFn>(() => Promise.resolve(null));

/** Two outcomes: resolves true on confirm, false on cancel/Escape/backdrop. */
export function useConfirm(): ConfirmFn {
  const ask = useContext(ChoiceContext);
  return useCallback(
    async (opts: ConfirmOptions) => {
      const picked = await ask({
        title: opts.title,
        message: opts.message,
        cancelLabel: opts.cancelLabel,
        choices: [{ id: "confirm", label: opts.confirmLabel ?? "", danger: opts.danger }],
      });
      return picked === "confirm";
    },
    [ask],
  );
}

/** Three or more outcomes. Resolves to the chosen id, or **null** when the user cancels,
 * presses Escape or clicks the backdrop — dismissal is never one of the actions. */
export function useChoice(): ChoiceFn {
  return useContext(ChoiceContext);
}

export function ConfirmProvider({ children }: { children: ReactNode }) {
  const { t } = useTranslation();
  const [state, setState] = useState<{
    opts: ChoiceOptions;
    resolve: (id: string | null) => void;
  } | null>(null);

  const ask = useCallback<ChoiceFn>(
    (opts) => new Promise<string | null>((resolve) => setState({ opts, resolve })),
    [],
  );

  function close(id: string | null) {
    state?.resolve(id);
    setState(null);
  }

  const choices = state?.opts.choices ?? [];
  // Focus Cancel when any offered action is destructive: the confirm button used to take
  // autoFocus unconditionally, so a stray Enter on an open dialog executed "Delete user" or
  // "Clear audit log" without the user ever looking at it.
  const anyDanger = choices.some((c) => c.danger);
  const multi = choices.length > 1;

  return (
    <ChoiceContext.Provider value={ask}>
      {children}
      {state && (
        <Modal
          title={state.opts.title ?? t("common.confirmTitle")}
          onClose={() => close(null)}
          maxWidth={choices.length > 1 ? "max-w-md" : "max-w-sm"}
        >
          <p className="text-sm text-muted leading-relaxed">{state.opts.message}</p>
          {/* One action: the familiar Cancel/Confirm row. Two or more: a column, because side by
              side they wrap raggedly and a wrapped button reads as a second, lesser group — and
              these are peers. Ordered least to most destructive, top to bottom. */}
          <div
            className={multi ? "flex flex-col gap-2 mt-5" : "flex justify-end gap-2 mt-5 flex-wrap"}
          >
            <button
              autoFocus={anyDanger}
              onClick={() => close(null)}
              className={`px-4 py-2 rounded-lg text-sm border border-border text-muted hover:text-fg hover:bg-surface transition ${
                multi ? "w-full order-last" : ""
              }`}
            >
              {state.opts.cancelLabel ?? t("common.cancel")}
            </button>
            {choices.map((c, i) => (
              <button
                key={c.id}
                autoFocus={!anyDanger && i === choices.length - 1}
                onClick={() => close(c.id)}
                className={`px-4 py-2 rounded-lg text-sm font-semibold transition ${
                  multi ? "w-full" : ""
                } ${
                  c.danger
                    ? "bg-red-500 text-white hover:bg-red-600"
                    : "bg-accent text-accent-fg hover:opacity-90"
                }`}
              >
                {c.label || t("common.confirm")}
              </button>
            ))}
          </div>
        </Modal>
      )}
    </ChoiceContext.Provider>
  );
}
