import {
  Alert,
  Badge,
  Group,
  Loader,
  MultiSelect,
  Radio,
  Stack,
  Text,
} from "@mantine/core";
import { IconInfoCircle, IconShieldCheck } from "@tabler/icons-react";
import { useEffect, useMemo, useState } from "react";
import { getAdminUsers } from "@/lib/features/users/query";

export type AccessMode = "specific" | "all";

type ConsoleUserOption = { value: string; label: string };

type Props = {
  mode: AccessMode;
  onModeChange: (m: AccessMode) => void;
  selected: string[];
  onSelectedChange: (ids: string[]) => void;
};

/**
 * Access model note, surfaced in the UI as well as here:
 *
 * Visibility is FAIL-CLOSED. A console user sees a dashboard only if they are a
 * super admin, hold dashboard create/update (a "dashboard admin"), or have an
 * explicit grant row. There is no "everyone" flag in the schema, so:
 *
 *   "Specific users" → grants exactly the chosen users.
 *   "All console users" → grants EVERY current console user, one row each. It
 *      is a bulk grant taken at this moment in time, NOT a standing rule:
 *      users created later are not covered and must be added.
 *
 * Admins and super admins are never listed, because they always have access
 * regardless of grants.
 */
const AccessPicker: React.FC<Props> = ({
  mode,
  onModeChange,
  selected,
  onSelectedChange,
}) => {
  const [users, setUsers] = useState<ConsoleUserOption[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setLoading(true);
      // Page size is generous so the picker holds the whole directory; the
      // console is in the low hundreds of users.
      const res = await getAdminUsers(1, 500);
      if (cancelled) return;
      const list = (res?.data as { users?: any[] } | null)?.users ?? [];
      setUsers(
        list.map((u) => ({
          value: u.id,
          label: `${[u.first_name, u.last_name].filter(Boolean).join(" ") || u.username || u.email} — ${u.email}`,
        })),
      );
      setLoading(false);
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  const allIds = useMemo(() => users.map((u) => u.value), [users]);

  // "All" is a bulk grant, so materialise it into the same id list the
  // specific mode uses — the API contract is identical either way.
  useEffect(() => {
    if (mode === "all" && allIds.length > 0) onSelectedChange(allIds);
  }, [mode, allIds]); // eslint-disable-line react-hooks/exhaustive-deps

  return (
    <Stack gap="md">
      <Alert
        variant="light"
        color="blue"
        radius="md"
        icon={<IconShieldCheck size={16} />}
      >
        <Text size="xs">
          Super admins and anyone with dashboard management permission{" "}
          <b>always see every dashboard</b>, whatever you choose here. This list
          controls everyone else — and it is fail-closed: a user with no grant
          sees nothing.
        </Text>
      </Alert>

      <Radio.Group
        value={mode}
        onChange={(v) => onModeChange(v as AccessMode)}
        label="Who can see this dashboard?"
      >
        <Stack gap="xs" mt="xs">
          <Radio
            value="specific"
            label="Specific people"
            description="Pick the console users who should see it."
          />
          <Radio
            value="all"
            label={
              <Group gap={6}>
                <Text size="sm">All current console users</Text>
                <Badge size="xs" variant="light" color="yellow">
                  snapshot
                </Badge>
              </Group>
            }
            description={
              loading
                ? "Loading directory…"
                : `Grants access to all ${allIds.length} console users that exist right now. Users added later will NOT be included automatically.`
            }
          />
        </Stack>
      </Radio.Group>

      {mode === "specific" && (
        <MultiSelect
          label="People"
          placeholder={loading ? "Loading console users…" : "Search by name or email"}
          data={users}
          value={selected}
          onChange={onSelectedChange}
          searchable
          clearable
          hidePickedOptions
          nothingFoundMessage="No matching console user"
          maxDropdownHeight={260}
          rightSection={loading ? <Loader size={14} /> : undefined}
          radius="md"
        />
      )}

      {mode === "all" && !loading && (
        <Alert variant="light" color="gray" radius="md" icon={<IconInfoCircle size={16} />}>
          <Text size="xs">
            {allIds.length} grants will be created. You can trim the list later
            from the dashboard's Access tab.
          </Text>
        </Alert>
      )}
    </Stack>
  );
};

export default AccessPicker;
