import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Check, RotateCcw, Shield, Trash2, UserPlus, X } from "lucide-react";
import { api, type AdminUserRow, type Invite, type Me } from "../lib/api";
import { notify } from "../lib/notifications";
import Tooltip from "./Tooltip";
import { useConfirm } from "./ConfirmProvider";

// Admin-only user & access management: roles, access requests (the Invite whitelist), and the
// demo whitelist + reset. Moved out of Settings → Account into its own admin page; the Invite
// and demo data are unchanged (same tables) — only the UI relocated.
export default function AdminUsers({ me }: { me: Me }) {
  return (
    <div className="p-4 max-w-3xl w-full mx-auto">
      <UsersRoles me={me} />
      <AdminInvites />
      <AdminDemo />
    </div>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <div className="glass rounded-2xl p-4 mb-4">
      <div className="text-xs uppercase tracking-wide text-muted mb-3">{title}</div>
      {children}
    </div>
  );
}

function Badge({ tone, children }: { tone: "accent" | "muted" | "warning"; children: React.ReactNode }) {
  const cls =
    tone === "accent"
      ? "border-accent/40 text-accent"
      : tone === "warning"
        ? "border-amber-500/40 text-amber-500"
        : "border-border text-muted";
  return (
    <span className={`shrink-0 text-[11px] px-2 py-0.5 rounded-full border ${cls}`}>{children}</span>
  );
}

function UsersRoles({ me }: { me: Me }) {
  const { t } = useTranslation();
  const qc = useQueryClient();
  const confirm = useConfirm();
  const q = useQuery({ queryKey: ["admin-users"], queryFn: api.adminUsers });
  const setRole = useMutation({
    mutationFn: ({ id, role }: { id: number; role: "user" | "admin" }) => api.setUserRole(id, role),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["admin-users"] });
      notify({ level: "success", message: t("users.roles.updated") });
    },
    // Errors (e.g. last-admin / self) surface via the global error dialog with the server's detail.
  });

  const onToggle = async (u: AdminUserRow) => {
    const makeAdmin = u.role !== "admin";
    const ok = await confirm({
      title: makeAdmin ? t("users.roles.promoteTitle") : t("users.roles.demoteTitle"),
      message: t(makeAdmin ? "users.roles.promoteConfirm" : "users.roles.demoteConfirm", {
        email: u.email,
      }),
      confirmLabel: makeAdmin ? t("users.roles.makeAdmin") : t("users.roles.makeUser"),
      danger: !makeAdmin,
    });
    if (ok) setRole.mutate({ id: u.id, role: makeAdmin ? "admin" : "user" });
  };

  const rows = q.data ?? [];

  return (
    <Section title={t("users.roles.title")}>
      <p className="text-xs text-muted leading-relaxed mb-3">{t("users.roles.intro")}</p>
      {rows.length === 0 ? (
        <p className="text-sm text-muted">{t("users.roles.empty")}</p>
      ) : (
        <div className="space-y-1.5">
          {rows.map((u) => {
            const self = u.id === me.id;
            return (
              <div key={u.id} className="glass-card flex items-center gap-2.5 p-2.5 rounded-xl">
                <div className="min-w-0 flex-1">
                  <div className="text-sm truncate">
                    {u.display_name ?? u.email.split("@")[0]}
                    {self && <span className="text-muted"> · {t("users.roles.you")}</span>}
                  </div>
                  <div className="text-[11px] text-muted truncate">{u.email}</div>
                </div>
                {u.role === "admin" && <Badge tone="accent">{t("users.roles.admin")}</Badge>}
                {u.is_demo && <Badge tone="muted">{t("users.roles.demo")}</Badge>}
                {!u.is_active && <Badge tone="warning">{t("users.roles.pending")}</Badge>}
                {u.is_active && !u.email_verified && (
                  <Badge tone="warning">{t("users.roles.unverified")}</Badge>
                )}
                <Tooltip
                  hint={
                    u.is_demo
                      ? t("users.roles.demoLocked")
                      : self
                        ? t("users.roles.selfLocked")
                        : u.role === "admin"
                          ? t("users.roles.makeUser")
                          : t("users.roles.makeAdmin")
                  }
                >
                  <button
                    onClick={() => onToggle(u)}
                    disabled={u.is_demo || self || setRole.isPending}
                    className="shrink-0 glass-card glass-hover inline-flex items-center gap-1 px-2.5 py-1.5 rounded-lg text-xs disabled:opacity-40 transition"
                  >
                    <Shield className="w-3.5 h-3.5" />
                    {u.role === "admin" ? t("users.roles.makeUser") : t("users.roles.makeAdmin")}
                  </button>
                </Tooltip>
              </div>
            );
          })}
        </div>
      )}
    </Section>
  );
}

// --- Access requests (the Invite whitelist) — moved verbatim from Settings → Account -------

function AdminInvites() {
  const { t } = useTranslation();
  const qc = useQueryClient();
  const invites = useQuery({ queryKey: ["admin-invites"], queryFn: () => api.adminInvites() });
  const [newEmail, setNewEmail] = useState("");
  const refresh = () => {
    qc.invalidateQueries({ queryKey: ["admin-invites"] });
    qc.invalidateQueries({ queryKey: ["me"] }); // updates the pending badge
  };
  const approve = useMutation({
    mutationFn: (id: number) => api.approveInvite(id),
    onSuccess: () => {
      refresh();
      notify({ level: "success", message: t("settings.invites.approved") });
    },
    onError: () => notify({ level: "error", message: t("settings.invites.approveFailed") }),
  });
  const deny = useMutation({
    mutationFn: (id: number) => api.denyInvite(id),
    onSuccess: refresh,
    onError: () => notify({ level: "error", message: t("settings.invites.denyFailed") }),
  });
  const add = useMutation({
    mutationFn: (email: string) => api.addInvite(email),
    onSuccess: () => {
      setNewEmail("");
      refresh();
      notify({ level: "success", message: t("settings.invites.addedToWhitelist") });
    },
    onError: () => notify({ level: "error", message: t("settings.invites.addFailed") }),
  });

  const list = invites.data ?? [];
  const pending = list.filter((i) => i.status === "pending");
  const decided = list.filter((i) => i.status !== "pending");

  return (
    <Section title={t("settings.invites.title")}>
      {pending.length === 0 ? (
        <p className="text-sm text-muted">{t("settings.invites.noPending")}</p>
      ) : (
        <div className="space-y-1.5">
          {pending.map((i) => (
            <InviteRow
              key={i.id}
              inv={i}
              onApprove={() => approve.mutate(i.id)}
              onDeny={() => deny.mutate(i.id)}
              busy={approve.isPending || deny.isPending}
            />
          ))}
        </div>
      )}

      <form
        onSubmit={(e) => {
          e.preventDefault();
          if (newEmail.trim()) add.mutate(newEmail.trim());
        }}
        className="flex items-center gap-2 mt-3"
      >
        <input
          type="email"
          value={newEmail}
          onChange={(e) => setNewEmail(e.target.value)}
          placeholder={t("settings.invites.addPlaceholder")}
          className="flex-1 min-w-0 bg-card border border-border rounded-xl px-3 py-2 text-sm outline-none focus:border-accent"
        />
        <button
          type="submit"
          className="shrink-0 glass-card glass-hover flex items-center gap-1.5 px-3 py-2 rounded-xl text-sm transition"
        >
          <UserPlus className="w-4 h-4" /> {t("settings.invites.add")}
        </button>
      </form>

      {decided.length > 0 && (
        <details className="mt-3">
          <summary className="text-xs text-muted cursor-pointer">
            {t("settings.invites.decided", { count: decided.length })}
          </summary>
          <div className="mt-2 space-y-1 text-xs text-muted">
            {decided.map((i) => (
              <div key={i.id} className="flex items-center justify-between gap-2">
                <span className="truncate">{i.email}</span>
                <span className={i.status === "approved" ? "text-accent" : "text-red-400"}>
                  {i.status}
                </span>
              </div>
            ))}
          </div>
        </details>
      )}
    </Section>
  );
}

function AdminDemo() {
  const { t } = useTranslation();
  const qc = useQueryClient();
  const confirm = useConfirm();
  const list = useQuery({ queryKey: ["demo-whitelist"], queryFn: () => api.adminDemoWhitelist() });
  const [newEmail, setNewEmail] = useState("");

  const add = useMutation({
    mutationFn: (email: string) => api.addDemoWhitelist(email),
    onSuccess: () => {
      setNewEmail("");
      qc.invalidateQueries({ queryKey: ["demo-whitelist"] });
      notify({ level: "success", message: t("settings.demo.added") });
    },
    onError: () => notify({ level: "error", message: t("settings.demo.addFailed") }),
  });
  const remove = useMutation({
    mutationFn: (id: number) => api.removeDemoWhitelist(id),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["demo-whitelist"] }),
    onError: () => notify({ level: "error", message: t("settings.demo.removeFailed") }),
  });
  const reset = useMutation({
    mutationFn: () => api.resetDemo(),
    onSuccess: (r: { playlists_seeded: number }) =>
      notify({
        level: "success",
        message: t("settings.demo.resetDone", { count: r.playlists_seeded }),
      }),
    onError: () => notify({ level: "error", message: t("settings.demo.resetFailed") }),
  });

  const rows = list.data ?? [];

  return (
    <Section title={t("settings.demo.title")}>
      <p className="text-xs text-muted leading-relaxed mb-2">{t("settings.demo.intro")}</p>

      {rows.length > 0 && (
        <div className="space-y-1.5 mb-3">
          {rows.map((r) => (
            <div key={r.id} className="glass-card flex items-center gap-2 p-2.5 rounded-xl">
              <div className="min-w-0 flex-1">
                <div className="text-sm truncate">{r.email}</div>
                {r.added_by && (
                  <div className="text-[11px] text-muted truncate">
                    {t("settings.demo.addedBy", { who: r.added_by })}
                  </div>
                )}
              </div>
              <Tooltip hint={t("settings.demo.removeHint")}>
                <button
                  onClick={() => remove.mutate(r.id)}
                  disabled={remove.isPending}
                  className="shrink-0 p-1.5 rounded-lg border border-border text-muted hover:text-red-400 disabled:opacity-50 transition"
                  aria-label={t("settings.demo.remove")}
                >
                  <Trash2 className="w-4 h-4" />
                </button>
              </Tooltip>
            </div>
          ))}
        </div>
      )}

      <form
        onSubmit={(e) => {
          e.preventDefault();
          if (newEmail.trim()) add.mutate(newEmail.trim());
        }}
        className="flex items-center gap-2"
      >
        <input
          type="email"
          value={newEmail}
          onChange={(e) => setNewEmail(e.target.value)}
          placeholder={t("settings.demo.addPlaceholder")}
          className="flex-1 min-w-0 bg-card border border-border rounded-xl px-3 py-2 text-sm outline-none focus:border-accent"
        />
        <button
          type="submit"
          className="shrink-0 glass-card glass-hover flex items-center gap-1.5 px-3 py-2 rounded-xl text-sm transition"
        >
          <UserPlus className="w-4 h-4" /> {t("settings.demo.add")}
        </button>
      </form>

      <div className="mt-4 pt-3 border-t border-border">
        <Tooltip hint={t("settings.demo.resetHint")}>
          <button
            onClick={async () => {
              if (
                await confirm({
                  title: t("settings.demo.resetTitle"),
                  message: t("settings.demo.resetConfirm"),
                  confirmLabel: t("settings.demo.reset"),
                  danger: true,
                })
              )
                reset.mutate();
            }}
            disabled={reset.isPending}
            className="glass-card glass-hover flex items-center gap-2 px-3 py-2 rounded-xl text-sm disabled:opacity-50 transition"
          >
            <RotateCcw className={`w-4 h-4 ${reset.isPending ? "animate-spin" : ""}`} />
            {t("settings.demo.reset")}
          </button>
        </Tooltip>
      </div>
    </Section>
  );
}

function InviteRow({
  inv,
  onApprove,
  onDeny,
  busy,
}: {
  inv: Invite;
  onApprove: () => void;
  onDeny: () => void;
  busy: boolean;
}) {
  const { t } = useTranslation();
  return (
    <div className="glass-card flex items-center gap-2 p-2.5 rounded-xl">
      <div className="min-w-0 flex-1">
        <div className="text-sm truncate">{inv.email}</div>
        {inv.requested_at && (
          <div className="text-[11px] text-muted">
            {t("settings.invites.requested", {
              time: new Date(inv.requested_at).toLocaleString(),
            })}
          </div>
        )}
      </div>
      <Tooltip hint={t("settings.invites.approveHint")}>
        <button
          onClick={onApprove}
          disabled={busy}
          className="shrink-0 p-1.5 rounded-lg border border-accent/40 text-accent hover:bg-accent/10 disabled:opacity-50 transition"
          aria-label={t("settings.invites.approve")}
        >
          <Check className="w-4 h-4" />
        </button>
      </Tooltip>
      <Tooltip hint={t("settings.invites.denyHint")}>
        <button
          onClick={onDeny}
          disabled={busy}
          className="shrink-0 p-1.5 rounded-lg border border-border text-muted hover:text-red-400 disabled:opacity-50 transition"
          aria-label={t("settings.invites.deny")}
        >
          <X className="w-4 h-4" />
        </button>
      </Tooltip>
    </div>
  );
}
