"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
import { DataTable } from "@open-mercato/ui/backend/DataTable";
import { Button } from "@open-mercato/ui/primitives/button";
import { RowActions } from "@open-mercato/ui/backend/RowActions";
import { apiCall, withScopedApiRequestHeaders } from "@open-mercato/ui/backend/utils/apiCall";
import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimisticLock";
import { raiseCrudError } from "@open-mercato/ui/backend/utils/serverErrors";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { flash } from "@open-mercato/ui/backend/FlashMessages";
import { buildOrganizationTreeOptions, formatOrganizationTreeLabel } from "@open-mercato/core/modules/directory/lib/tree";
import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
import { ListEmptyState } from "@open-mercato/ui/backend/filters/ListEmptyState";
async function fetchOrganizationFilterOptions() {
  const search = new URLSearchParams();
  search.set("view", "tree");
  search.set("status", "all");
  try {
    const call = await apiCall(
      `/api/directory/organizations?${search.toString()}`
    );
    if (!call.ok) return [];
    const nodes = Array.isArray(call.result?.items) ? call.result.items : [];
    const flattened = buildOrganizationTreeOptions(nodes);
    return flattened.filter((opt) => typeof opt.value === "string" && opt.value.length > 0).map((opt) => {
      const baseLabel = opt.name && opt.name.length > 0 ? opt.name : opt.value;
      const depth = typeof opt.depth === "number" ? opt.depth : 0;
      const label = `${formatOrganizationTreeLabel(baseLabel, depth)}${opt.isActive === false ? " (inactive)" : ""}`;
      return { value: opt.value, label };
    });
  } catch {
    return [];
  }
}
async function fetchRoleFilterOptions(query) {
  const search = new URLSearchParams();
  search.set("page", "1");
  search.set("pageSize", "50");
  if (query && query.trim()) search.set("search", query.trim());
  try {
    const call = await apiCall(`/api/auth/roles?${search.toString()}`);
    if (!call.ok) return [];
    const items = Array.isArray(call.result?.items) ? call.result.items : [];
    return items.map((item) => {
      const id = typeof item?.id === "string" ? item.id : null;
      const name = typeof item?.name === "string" ? item.name : null;
      if (!id || !name) return null;
      return { value: id, label: name };
    }).filter((opt) => opt !== null);
  } catch {
    return [];
  }
}
async function fetchRoleOptionsByIds(ids) {
  const unique = Array.from(new Set(ids.filter((id) => typeof id === "string" && id.trim() !== "")));
  if (unique.length === 0) return [];
  const results = await Promise.all(unique.map(async (id) => {
    try {
      const search = new URLSearchParams();
      search.set("id", id);
      search.set("page", "1");
      search.set("pageSize", "1");
      const call = await apiCall(`/api/auth/roles?${search.toString()}`);
      if (!call.ok) return null;
      const data = call.result;
      const items = Array.isArray(data?.items) ? data?.items : [];
      const match = items.find((item) => {
        if (!item || typeof item !== "object") return false;
        const entry = item;
        return typeof entry.id === "string" && entry.id === id;
      });
      const record = match && typeof match === "object" ? match : null;
      const name = typeof record?.name === "string" ? record.name : null;
      if (!name) return null;
      return { value: id, label: name };
    } catch {
      return null;
    }
  }));
  return results.filter((opt) => opt !== null);
}
function mergeOptions(existing, next) {
  if (!next.length) return existing;
  const map = /* @__PURE__ */ new Map();
  for (const opt of existing) map.set(opt.value, opt);
  for (const opt of next) map.set(opt.value, opt);
  return Array.from(map.values()).sort((a, b) => a.label.localeCompare(b.label));
}
function arraysEqual(a, b) {
  if (a.length !== b.length) return false;
  for (let i = 0; i < a.length; i += 1) {
    if (a[i] !== b[i]) return false;
  }
  return true;
}
function UsersListPage() {
  const { confirm, ConfirmDialogElement } = useConfirmDialog();
  const searchParams = useSearchParams();
  const scopeVersion = useOrganizationScopeVersion();
  const queryClient = useQueryClient();
  const t = useT();
  const [sorting, setSorting] = React.useState([{ id: "email", desc: false }]);
  const [page, setPage] = React.useState(1);
  const [search, setSearch] = React.useState("");
  const [filterValues, setFilterValues] = React.useState({});
  const [organizationOptions, setOrganizationOptions] = React.useState([]);
  const [roleOptions, setRoleOptions] = React.useState([]);
  const [roleIdToLabel, setRoleIdToLabel] = React.useState({});
  const [roleFilterDirty, setRoleFilterDirty] = React.useState(false);
  const roleIdsFromUrl = React.useMemo(() => {
    if (!searchParams) return [];
    const raw = searchParams.getAll("roleId");
    return raw.filter((id) => typeof id === "string" && id.trim() !== "");
  }, [searchParams]);
  const roleIdsFromUrlKey = React.useMemo(() => roleIdsFromUrl.join("|"), [roleIdsFromUrl]);
  const organizationId = typeof filterValues.organizationId === "string" && filterValues.organizationId ? filterValues.organizationId : void 0;
  const applyRoleOptions = React.useCallback((opts) => {
    if (!opts.length) return;
    setRoleOptions((prev) => mergeOptions(prev, opts));
    setRoleIdToLabel((prev) => {
      if (!opts.length) return prev;
      const next = { ...prev };
      for (const opt of opts) next[opt.value] = opt.label;
      return next;
    });
  }, []);
  React.useEffect(() => {
    let cancelled = false;
    fetchOrganizationFilterOptions().then((opts) => {
      if (!cancelled) setOrganizationOptions(opts);
    });
    return () => {
      cancelled = true;
    };
  }, [scopeVersion]);
  React.useEffect(() => {
    let cancelled = false;
    fetchRoleFilterOptions().then((opts) => {
      if (!cancelled) applyRoleOptions(opts);
    });
    return () => {
      cancelled = true;
    };
  }, [applyRoleOptions]);
  React.useEffect(() => {
    if (roleFilterDirty) return;
    if (roleIdsFromUrl.length === 0) {
      setFilterValues((prev) => {
        if (!Array.isArray(prev.roles) || prev.roles.length === 0) return prev;
        const next = { ...prev };
        delete next.roles;
        return next;
      });
      return;
    }
    const missing = roleIdsFromUrl.filter((id) => !roleIdToLabel[id]);
    if (missing.length === 0) {
      setFilterValues((prev) => {
        const current = Array.isArray(prev.roles) ? prev.roles : [];
        if (arraysEqual(current, roleIdsFromUrl)) return prev;
        return { ...prev, roles: roleIdsFromUrl };
      });
      return;
    }
    let cancelled = false;
    (async () => {
      const fetched = await fetchRoleOptionsByIds(missing);
      if (cancelled) return;
      if (fetched.length) applyRoleOptions(fetched);
      setFilterValues((prev) => {
        const current = Array.isArray(prev.roles) ? prev.roles : [];
        if (arraysEqual(current, roleIdsFromUrl)) return prev;
        return { ...prev, roles: roleIdsFromUrl };
      });
    })();
    return () => {
      cancelled = true;
    };
  }, [roleFilterDirty, roleIdsFromUrlKey, roleIdsFromUrl, roleIdToLabel, applyRoleOptions]);
  React.useEffect(() => {
    setRoleFilterDirty(false);
  }, [roleIdsFromUrlKey]);
  const loadRoleOptions = React.useCallback(async (query) => {
    const opts = await fetchRoleFilterOptions(query);
    if (opts.length) applyRoleOptions(opts);
    return opts;
  }, [applyRoleOptions]);
  const filters = React.useMemo(() => [
    {
      id: "name",
      label: t("auth.users.list.filters.name", "Display name"),
      type: "text",
      placeholder: t("auth.users.list.filters.namePlaceholder", "Filter by display name")
    },
    {
      id: "organizationId",
      label: t("auth.users.list.filters.organization", "Organization"),
      type: "select",
      options: organizationOptions
    },
    {
      id: "roles",
      label: t("auth.users.list.filters.roles", "Roles"),
      type: "tags",
      placeholder: t("auth.users.list.filters.rolesPlaceholder", "Filter by roles"),
      options: roleOptions,
      loadOptions: loadRoleOptions,
      formatValue: (val) => roleIdToLabel[val] ?? val
    }
  ], [organizationOptions, roleOptions, loadRoleOptions, roleIdToLabel, t]);
  const roleIdsFromFilter = React.useMemo(() => {
    const raw = Array.isArray(filterValues.roles) ? filterValues.roles : [];
    return raw.filter((id) => typeof id === "string" && id.length > 0);
  }, [filterValues.roles]);
  const effectiveRoleIds = React.useMemo(() => {
    if (roleFilterDirty) return roleIdsFromFilter;
    if (roleIdsFromFilter.length > 0) return roleIdsFromFilter;
    return roleIdsFromUrl;
  }, [roleFilterDirty, roleIdsFromFilter, roleIdsFromUrl]);
  const normalizedRoleIds = React.useMemo(() => {
    if (!effectiveRoleIds.length) return [];
    const unique = Array.from(new Set(effectiveRoleIds));
    unique.sort((a, b) => a.localeCompare(b));
    return unique;
  }, [effectiveRoleIds]);
  const handleSearchChange = React.useCallback((value) => {
    setSearch(value);
    setPage(1);
  }, []);
  const handleFiltersApply = React.useCallback((values) => {
    const next = {};
    const name = typeof values.name === "string" ? values.name.trim() : "";
    if (name) next.name = name;
    const org = typeof values.organizationId === "string" ? values.organizationId.trim() : "";
    if (org) next.organizationId = org;
    const rawRoles = Array.isArray(values.roles) ? values.roles : [];
    const sanitizedRoles = rawRoles.map((role) => role.trim()).filter((role) => role.length > 0);
    if (sanitizedRoles.length) next.roles = sanitizedRoles;
    setFilterValues(next);
    setRoleFilterDirty(true);
    setPage(1);
  }, []);
  const handleFiltersClear = React.useCallback(() => {
    setFilterValues({});
    setRoleFilterDirty(true);
    setPage(1);
  }, []);
  const exportParams = React.useMemo(() => {
    const name = typeof filterValues.name === "string" ? filterValues.name.trim() : "";
    return {
      page,
      pageSize: 50,
      search,
      name: name.length ? name : void 0,
      organizationId,
      roleIds: normalizedRoleIds
    };
  }, [filterValues.name, normalizedRoleIds, organizationId, page, search]);
  const exportConfig = React.useMemo(() => ({
    view: {
      getUrl: (format) => {
        const params2 = new URLSearchParams();
        params2.set("page", String(exportParams.page));
        params2.set("pageSize", String(exportParams.pageSize));
        if (exportParams.search) params2.set("search", exportParams.search);
        if (exportParams.name) params2.set("name", exportParams.name);
        if (exportParams.organizationId) params2.set("organizationId", exportParams.organizationId);
        for (const roleId of exportParams.roleIds) params2.append("roleId", roleId);
        params2.set("format", format);
        params2.set("exportScope", "view");
        return `/api/auth/users?${params2.toString()}`;
      }
    },
    full: {
      getUrl: (format) => {
        const params2 = new URLSearchParams();
        params2.set("page", String(exportParams.page));
        params2.set("pageSize", String(exportParams.pageSize));
        if (exportParams.search) params2.set("search", exportParams.search);
        if (exportParams.name) params2.set("name", exportParams.name);
        if (exportParams.organizationId) params2.set("organizationId", exportParams.organizationId);
        for (const roleId of exportParams.roleIds) params2.append("roleId", roleId);
        params2.set("format", format);
        params2.set("exportScope", "full");
        params2.set("all", "true");
        return `/api/auth/users?${params2.toString()}`;
      }
    }
  }), [exportParams]);
  const params = React.useMemo(() => {
    const p = new URLSearchParams();
    p.set("page", String(page));
    p.set("pageSize", "50");
    if (search) p.set("search", search);
    const name = typeof filterValues.name === "string" ? filterValues.name.trim() : "";
    if (name) p.set("name", name);
    if (organizationId) p.set("organizationId", organizationId);
    if (normalizedRoleIds.length) {
      for (const id of normalizedRoleIds) p.append("roleId", id);
    }
    return p.toString();
  }, [filterValues.name, page, search, organizationId, normalizedRoleIds]);
  const { data: usersData, isLoading } = useQuery({
    queryKey: ["users", params, scopeVersion],
    queryFn: async () => {
      const call = await apiCall(
        `/api/auth/users?${params}`
      );
      if (!call.ok) {
        await raiseCrudError(call.response, t("auth.users.list.error.load", "Failed to load users"));
      }
      return call.result ?? { items: [], total: 0, totalPages: 1 };
    }
  });
  const rows = usersData?.items || [];
  const total = usersData?.total || 0;
  const totalPages = usersData?.totalPages || 1;
  const isSuperAdmin = !!usersData?.isSuperAdmin;
  const rowsWithOrgNames = React.useMemo(() => rows.map((row) => ({
    ...row,
    organizationName: row.organizationName ?? (row.organizationId ?? void 0),
    tenantName: row.tenantName ?? (row.tenantId ?? void 0)
  })), [rows]);
  const showTenantColumn = React.useMemo(
    () => isSuperAdmin && rowsWithOrgNames.some((row) => row.tenantName),
    [isSuperAdmin, rowsWithOrgNames]
  );
  const columns = React.useMemo(() => {
    const base = [
      { accessorKey: "email", header: "Email" },
      { accessorKey: "name", header: t("auth.users.list.columns.name", "Display name") },
      { accessorKey: "organizationName", header: "Organization" },
      { accessorKey: "roles", header: "Roles", cell: ({ row }) => (row.original.roles || []).join(", ") }
    ];
    if (showTenantColumn) {
      base.splice(1, 0, { accessorKey: "tenantName", header: "Tenant" });
    }
    return base;
  }, [showTenantColumn, t]);
  const handleDelete = React.useCallback(async (row) => {
    const confirmed = await confirm({
      title: t("auth.users.list.confirmDelete", 'Delete user "{email}"?', { email: row.email }),
      variant: "destructive"
    });
    if (!confirmed) return;
    const deleteErrorMessage = t("auth.users.list.error.delete", "Failed to delete user");
    try {
      const call = await withScopedApiRequestHeaders(
        buildOptimisticLockHeader(row.updatedAt),
        () => apiCall(`/api/auth/users?id=${encodeURIComponent(row.id)}`, { method: "DELETE" })
      );
      if (!call.ok) {
        await raiseCrudError(call.response, deleteErrorMessage);
      }
      flash(t("auth.users.flash.deleted", "User deleted"), "success");
      await queryClient.invalidateQueries({ queryKey: ["users"] });
    } catch (error) {
      const message = error instanceof Error ? error.message : deleteErrorMessage;
      flash(message, "error");
    }
  }, [confirm, queryClient, t]);
  return /* @__PURE__ */ jsxs(Page, { children: [
    /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
      DataTable,
      {
        title: t("auth.users.list.title", "Users"),
        actions: /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href: "/backend/users/create", children: t("common.create", "Create") }) }),
        columns,
        data: rowsWithOrgNames,
        exporter: exportConfig,
        searchValue: search,
        onSearchChange: handleSearchChange,
        filters,
        filterValues,
        onFiltersApply: handleFiltersApply,
        onFiltersClear: handleFiltersClear,
        sortable: true,
        sorting,
        onSortingChange: setSorting,
        perspective: { tableId: "auth.users.list" },
        emptyState: /* @__PURE__ */ jsx(
          ListEmptyState,
          {
            entityName: t("auth.users.list.title", "Users"),
            createHref: "/backend/users/create",
            createLabel: t("common.create", "Create")
          }
        ),
        rowActions: (row) => /* @__PURE__ */ jsx(RowActions, { items: [
          { id: "edit", label: t("common.edit", "Edit"), href: `/backend/users/${row.id}/edit` },
          { id: "show-roles", label: t("auth.users.list.actions.showRoles", "Show roles"), href: `/backend/roles?userId=${encodeURIComponent(row.id)}` },
          { id: "delete", label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
            void handleDelete(row);
          } }
        ] }),
        pagination: { page, pageSize: 50, total, totalPages, onPageChange: setPage },
        isLoading
      }
    ) }),
    ConfirmDialogElement
  ] });
}
export {
  UsersListPage as default
};
//# sourceMappingURL=page.js.map
