import { useEffect, useMemo, useRef, useState } from "react";
import { KeyRound, Pencil, Plus, Search, Trash2 } from "lucide-react";
import type { ApiSettings, AuthInfo } from "@govoplan/core-webui";
import { createUser, fetchGroupsDelta, fetchRolesDelta, fetchUserAccessExplanation, fetchUsersDelta, updateUser, type AccessRoleSourceItem, type FunctionFactExplanationItem, type GroupSummary, type RoleSummary, type UserAccessExplanationResponse, type UserAdminItem } from "../../api/admin";
import { Button } from "@govoplan/core-webui";
import { DataGrid, type DataGridColumn } from "@govoplan/core-webui";
import { Dialog } from "@govoplan/core-webui";
import { FormField } from "@govoplan/core-webui";
import { PasswordField } from "@govoplan/core-webui";
import { StatusBadge } from "@govoplan/core-webui";
import { ToggleSwitch } from "@govoplan/core-webui";
import { ConfirmDialog } from "@govoplan/core-webui";
import { AdminIconButton, AdminPageLayout, AdminSelectionList, TableActionGroup, adminErrorMessage, formatAdminDateTime as formatDateTime, joinLabels } from "@govoplan/core-webui";
import { hasTenantWildcard, i18nMessage, useDeltaWatermarks, useUnsavedDraftGuard } from "@govoplan/core-webui";
import { loadDeltaRows } from "./utils/deltaRows";

const emptyDraft = {
  email: "",
  displayName: "",
  password: "",
  passwordResetRequired: true,
  isActive: true,
  groupIds: [] as string[],
  roleIds: [] as string[]
};

export default function UsersPanel({ settings, auth, canCreate, canUpdate, canSuspend, canManageGroups, canAssignRoles, onAuthRefresh








}: {settings: ApiSettings;auth: AuthInfo;canCreate: boolean;canUpdate: boolean;canSuspend: boolean;canManageGroups: boolean;canAssignRoles: boolean;onAuthRefresh: () => Promise<void>;}) {
  const [users, setUsers] = useState<UserAdminItem[]>([]);
  const [groups, setGroups] = useState<GroupSummary[]>([]);
  const [roles, setRoles] = useState<RoleSummary[]>([]);
  const usersRef = useRef<UserAdminItem[]>([]);
  const groupsRef = useRef<GroupSummary[]>([]);
  const rolesRef = useRef<RoleSummary[]>([]);
  const { getDeltaWatermark, setDeltaWatermark, resetDeltaWatermark } = useDeltaWatermarks();
  const [editing, setEditing] = useState<UserAdminItem | "new" | null>(null);
  const [viewing, setViewing] = useState<UserAdminItem | null>(null);
  const [explaining, setExplaining] = useState<UserAdminItem | null>(null);
  const [accessExplanation, setAccessExplanation] = useState<UserAccessExplanationResponse | null>(null);
  const [accessExplanationLoading, setAccessExplanationLoading] = useState(false);
  const [deactivating, setDeactivating] = useState<UserAdminItem | null>(null);
  const [draft, setDraft] = useState(emptyDraft);
  const [savedDraftKey, setSavedDraftKey] = useState(draftKey(emptyDraft));
  const [temporaryPassword, setTemporaryPassword] = useState<{email: string;password: string;} | null>(null);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [success, setSuccess] = useState("");
  const dirty = editing !== null && draftKey(draft) !== savedDraftKey;

  useUnsavedDraftGuard({
    dirty,
    onSave: save,
    onDiscard: closeEditor
  });

  async function load() {
    setLoading(true);
    setError("");
    try {
      const [nextUsers, nextGroups, nextRoles] = await Promise.all([
      loadDeltaRows(usersRef.current, "access:users", getDeltaWatermark, setDeltaWatermark, (since) => fetchUsersDelta(settings, { since }), (response) => response.users, (user) => user.id, "access_user", sortUsers),
      loadDeltaRows(groupsRef.current, "access:groups", getDeltaWatermark, setDeltaWatermark, (since) => fetchGroupsDelta(settings, { since }), (response) => response.groups, (group) => group.id, "access_group", sortGroups),
      loadDeltaRows(rolesRef.current, "access:roles", getDeltaWatermark, setDeltaWatermark, (since) => fetchRolesDelta(settings, { since }), (response) => response.roles, (role) => role.id, "access_role", sortTenantRoles)]
      );
      usersRef.current = nextUsers;
      groupsRef.current = nextGroups;
      rolesRef.current = nextRoles;
      setUsers(nextUsers);
      setGroups(nextGroups);
      setRoles(nextRoles.filter((role) => role.is_assignable));
    } catch (err) {setError(adminErrorMessage(err));} finally
    {setLoading(false);}
  }

  useEffect(() => {
    usersRef.current = [];
    groupsRef.current = [];
    rolesRef.current = [];
    resetDeltaWatermark();
    void load();
  }, [settings.accessToken, settings.apiBaseUrl, (auth.active_tenant ?? auth.tenant).id, resetDeltaWatermark]);

  function openCreate() {
    setDraft(emptyDraft);
    setSavedDraftKey(draftKey(emptyDraft));
    setEditing("new");
    setError("");
  }

  function openEdit(user: UserAdminItem) {
    const nextDraft = {
      email: user.email,
      displayName: user.display_name || "",
      password: "",
      passwordResetRequired: user.password_reset_required,
      isActive: user.is_active,
      groupIds: user.groups.map((group) => group.id),
      roleIds: user.roles.map((role) => role.id)
    };
    setDraft(nextDraft);
    setSavedDraftKey(draftKey(nextDraft));
    setEditing(user);
    setError("");
  }

  function closeEditor() {
    setEditing(null);
    setDraft(emptyDraft);
    setSavedDraftKey(draftKey(emptyDraft));
  }

  async function save(): Promise<boolean> {
    setBusy(true);
    setError("");
    try {
      if (editing === "new") {
        const response = await createUser(settings, {
          email: draft.email,
          display_name: draft.displayName || null,
          password: draft.password || null,
          password_reset_required: draft.passwordResetRequired,
          is_active: draft.isActive,
          group_ids: canManageGroups ? draft.groupIds : [],
          role_ids: canAssignRoles ? draft.roleIds : []
        });
        setSuccess(i18nMessage("i18n:govoplan-access.tenant_membership_created_for_value.2b8eeef6", { value0: response.user.email }));
        if (response.temporary_password) setTemporaryPassword({ email: response.user.email, password: response.temporary_password });
      } else if (editing) {
        const payload: Parameters<typeof updateUser>[2] = {};
        if (canUpdate) payload.display_name = draft.displayName || null;
        if (canSuspend) payload.is_active = draft.isActive;
        if (canManageGroups) payload.group_ids = draft.groupIds;
        if (canAssignRoles) payload.role_ids = draft.roleIds;
        await updateUser(settings, editing.id, payload);
        setSuccess(i18nMessage("i18n:govoplan-access.access_updated_for_value.87f22245", { value0: editing.email }));
        if (editing.id === auth.user.id) await onAuthRefresh();
      }
      setEditing(null);
      await load();
      return true;
    } catch (err) {setError(adminErrorMessage(err));return false;} finally
    {setBusy(false);}
  }

  async function deactivate() {
    if (!deactivating) return;
    setBusy(true);
    setError("");
    try {
      await updateUser(settings, deactivating.id, { is_active: false });
      setSuccess(i18nMessage("i18n:govoplan-access.value_deactivated_in_this_tenant.871837c2", { value0: deactivating.email }));
      if (deactivating.id === auth.user.id) await onAuthRefresh();
      setDeactivating(null);
      await load();
    } catch (err) {setError(adminErrorMessage(err));} finally
    {setBusy(false);}
  }

  async function openAccessExplanation(user: UserAdminItem) {
    setExplaining(user);
    setAccessExplanation(null);
    setAccessExplanationLoading(true);
    setError("");
    try {
      setAccessExplanation(await fetchUserAccessExplanation(settings, user.id));
    } catch (err) {
      setError(adminErrorMessage(err));
      setExplaining(null);
    } finally {
      setAccessExplanationLoading(false);
    }
  }

  const columns = useMemo<DataGridColumn<UserAdminItem>[]>(() => [
  { id: "user", header: "i18n:govoplan-access.user.9f8a2389", width: "minmax(230px, 1fr)", minWidth: 210, resizable: true, sticky: "start", sortable: true, filterable: true, value: (row) => `${row.display_name || ""} ${row.email}`, render: (row) => <div><strong>{row.display_name || row.email}</strong><div className="muted small-note">{row.email}</div></div> },
  { id: "groups", header: "i18n:govoplan-access.groups.ae9629f4", width: 210, minWidth: 150, maxWidth: 420, resizable: true, sortable: true, filterable: true, value: (row) => joinLabels(row.groups) },
  { id: "roles", header: "i18n:govoplan-access.direct_roles.c4db7156", width: 220, minWidth: 150, maxWidth: 460, resizable: true, fill: true, sortable: true, filterable: true, value: (row) => joinLabels(row.roles) },
  { id: "scope_count", header: "i18n:govoplan-access.permissions.d06d5557", width: 110, resizable: false, sortable: true, filterable: true, filterType: "integer", value: (row) => hasTenantWildcard(row.effective_scopes) ? 999 : row.effective_scopes.length, render: (row) => hasTenantWildcard(row.effective_scopes) ? "i18n:govoplan-access.all.6a720856" : String(row.effective_scopes.length) },
  { id: "status", header: "i18n:govoplan-access.status.bae7d5be", width: 120, resizable: false, sortable: true, filterable: true, value: (row) => row.is_active && row.account_is_active ? "active" : "inactive", render: (row) => <StatusBadge status={row.is_active && row.account_is_active ? "active" : "inactive"} /> },
  { id: "last_login", header: "i18n:govoplan-access.last_login.43dab84f", width: 180, minWidth: 150, resizable: true, sortable: true, value: (row) => row.last_login_at || "", render: (row) => formatDateTime(row.last_login_at) },
  { id: "actions", header: "i18n:govoplan-access.actions.c3cd636a", width: 190, sticky: "end", resizable: false, align: "right", render: (row) => <TableActionGroup actions={[
      { id: "inspect", label: i18nMessage("i18n:govoplan-access.inspect_value.9d5d1071", { value0: row.email }), icon: <Search />, onClick: () => setViewing(row) },
      { id: "explain", label: i18nMessage("i18n:govoplan-access.explain_access_for_value.3af96e47", { value0: row.email }), icon: <KeyRound />, onClick: () => void openAccessExplanation(row) },
      { id: "edit", label: i18nMessage("i18n:govoplan-access.edit_value.fad75899", { value0: row.email }), icon: <Pencil />, disabled: !(canUpdate || canSuspend || canManageGroups || canAssignRoles), onClick: () => openEdit(row) },
      { id: "deactivate", label: i18nMessage("i18n:govoplan-access.deactivate_value.a276a667", { value0: row.email }), icon: <Trash2 />, variant: "danger", applicable: row.is_active, disabled: !canSuspend || row.is_last_active_owner, onClick: () => setDeactivating(row) }
    ]} /> }],
  [canAssignRoles, canManageGroups, canSuspend, canUpdate, settings]);

  return (
    <>
      <AdminPageLayout title="i18n:govoplan-access.tenant_users.cb800b38" description="i18n:govoplan-access.manage_memberships_groups_and_direct_roles_in_th.25af86bb" loading={loading} error={error} success={success} actions={<><Button onClick={() => void load()} disabled={loading}>i18n:govoplan-access.reload.cce71553</Button><AdminIconButton label="i18n:govoplan-access.add_tenant_user.36f37ce7" icon={<Plus />} variant="primary" onClick={openCreate} disabled={!canCreate} /></>}>
        <div className="admin-table-surface"><DataGrid id="admin-users-v3" rows={users} columns={columns} initialFit="container" getRowKey={(row) => row.id} emptyText="i18n:govoplan-access.no_tenant_users_found.74bb615f" /></div>
      </AdminPageLayout>

      <Dialog open={editing !== null} title={editing === "new" ? "i18n:govoplan-access.add_tenant_user.36f37ce7" : "i18n:govoplan-access.edit_tenant_user.99121a61"} onClose={() => !busy && setEditing(null)} className="admin-dialog admin-dialog-wide" footer={<><Button onClick={() => setEditing(null)} disabled={busy}>i18n:govoplan-access.cancel.77dfd213</Button><Button variant="primary" onClick={() => void save()} disabled={busy || !draft.email.trim() || (editing === "new" ? !canCreate : !(canUpdate || canSuspend || canManageGroups || canAssignRoles))}>{busy ? "i18n:govoplan-access.saving.56a2285c" : "i18n:govoplan-access.save_user.0d071b89"}</Button></>}>
        <div className="admin-form-grid two-columns">
          <FormField label="i18n:govoplan-access.email.84add5b2"><input value={draft.email} disabled={editing !== "new"} onChange={(event) => setDraft({ ...draft, email: event.target.value })} /></FormField>
          <FormField label="i18n:govoplan-access.display_name.c7874aaa"><input value={draft.displayName} disabled={editing !== "new" && !canUpdate} onChange={(event) => setDraft({ ...draft, displayName: event.target.value })} /></FormField>
          {editing === "new" &&
          <FormField label="i18n:govoplan-access.initial_password.2278be8c">
              <PasswordField
              value={draft.password}
              placeholder="i18n:govoplan-access.leave_empty_to_generate.e58222d8"
              autoComplete="new-password"
              onValueChange={(password) => setDraft({ ...draft, password })} />
            
            </FormField>
          }
          <FormField label="i18n:govoplan-access.membership_status.b77fc732"><select value={draft.isActive ? "active" : "inactive"} disabled={Boolean(editing && editing !== "new" && (!canSuspend || editing.is_last_active_owner))} onChange={(event) => setDraft({ ...draft, isActive: event.target.value === "active" })}><option value="active">i18n:govoplan-access.active.a733b809</option><option value="inactive">i18n:govoplan-access.inactive.09af574c</option></select></FormField>
        </div>
        {editing === "new" && <ToggleSwitch label="i18n:govoplan-access.require_password_change_when_account_settings_ar.69bce7a3" checked={draft.passwordResetRequired} onChange={(passwordResetRequired) => setDraft({ ...draft, passwordResetRequired })} />}
        {editing && editing !== "new" && editing.is_last_active_owner && <p className="admin-protection-note">i18n:govoplan-access.this_membership_is_the_tenant_s_last_active_oper.072b247f</p>}
        <div className="admin-assignment-grid">
          <div><span className="form-label">i18n:govoplan-access.groups.ae9629f4</span><AdminSelectionList options={groups.filter((group) => group.is_active).map((group) => ({ id: group.id, label: group.name, description: group.description, disabled: !canManageGroups }))} selected={draft.groupIds} onChange={(groupIds) => setDraft({ ...draft, groupIds })} emptyText="i18n:govoplan-access.no_groups_exist_yet.9cd029f6" /></div>
          <div><span className="form-label">i18n:govoplan-access.direct_roles.c4db7156</span><AdminSelectionList options={roles.map((role) => ({ id: role.id, label: role.name, description: role.description, disabled: !canAssignRoles }))} selected={draft.roleIds} onChange={(roleIds) => setDraft({ ...draft, roleIds })} emptyText="i18n:govoplan-access.no_assignable_roles_exist.a4c268c2" /></div>
        </div>
        <p className="muted small-note">i18n:govoplan-access.group_roles_and_direct_roles_are_combined_the_ba.a43c2f16</p>
      </Dialog>

      <Dialog open={Boolean(viewing)} title="i18n:govoplan-access.tenant_user_details.fbab9079" onClose={() => setViewing(null)} className="admin-dialog admin-dialog-wide" footer={<Button onClick={() => setViewing(null)}>i18n:govoplan-access.close.bbfa773e</Button>}>
        {viewing && <dl className="admin-details-grid">
          <div><dt>i18n:govoplan-access.user.9f8a2389</dt><dd>{viewing.display_name || viewing.email}</dd></div><div><dt>i18n:govoplan-access.email.84add5b2</dt><dd>{viewing.email}</dd></div>
          <div><dt>i18n:govoplan-access.membership.53bc9670</dt><dd>{viewing.is_active ? "i18n:govoplan-access.active.a733b809" : "i18n:govoplan-access.inactive.09af574c"}</dd></div><div><dt>i18n:govoplan-access.global_account.e1b00cf5</dt><dd>{viewing.account_is_active ? "i18n:govoplan-access.active.a733b809" : "i18n:govoplan-access.inactive.09af574c"}</dd></div>
          <div><dt>i18n:govoplan-access.groups.ae9629f4</dt><dd>{joinLabels(viewing.groups)}</dd></div><div><dt>i18n:govoplan-access.direct_roles.c4db7156</dt><dd>{joinLabels(viewing.roles)}</dd></div>
          <div><dt>i18n:govoplan-access.effective_permissions.17c0fe8a</dt><dd>{hasTenantWildcard(viewing.effective_scopes) ? "i18n:govoplan-access.all_tenant_permissions.cca8b6e4" : viewing.effective_scopes.join(", ") || "i18n:govoplan-access.none.6eef6648"}</dd></div><div><dt>i18n:govoplan-access.last_login.43dab84f</dt><dd>{formatDateTime(viewing.last_login_at)}</dd></div>
        </dl>}
      </Dialog>

      <Dialog open={Boolean(explaining)} title="i18n:govoplan-access.access_explanation.75ee7f62" onClose={() => { if (!accessExplanationLoading) { setExplaining(null); setAccessExplanation(null); } }} className="admin-dialog admin-dialog-wide" footer={<Button onClick={() => { setExplaining(null); setAccessExplanation(null); }} disabled={accessExplanationLoading}>i18n:govoplan-access.close.bbfa773e</Button>}>
        {accessExplanationLoading && <p className="muted small-note">i18n:govoplan-access.loading_access_explanation.04a7c934</p>}
        {accessExplanation && <>
          <dl className="admin-details-grid">
            <div><dt>i18n:govoplan-access.user.9f8a2389</dt><dd>{accessExplanation.user.display_name || accessExplanation.user.email}</dd></div>
            <div><dt>i18n:govoplan-access.account.85dfa32c</dt><dd>{accessExplanation.user.account_id}</dd></div>
            <div><dt>i18n:govoplan-access.role_sources.6f42a672</dt><dd>{accessExplanation.role_sources.length}</dd></div>
            <div><dt>i18n:govoplan-access.function_facts.848b32cc</dt><dd>{accessExplanation.function_facts.length}</dd></div>
          </dl>
          <h3>i18n:govoplan-access.role_sources.6f42a672</h3>
          {accessExplanation.role_sources.length ? <div className="admin-assignment-grid">
            {accessExplanation.role_sources.map((source) => <div key={sourceKey(source)}>
              <strong>{source.role_name}</strong>
              <div className="muted small-note">
                <span>{sourceTypeLabel(source)}</span>
                {source.group_name && <> - <span>i18n:govoplan-access.group.171a0606</span>: {source.group_name}</>}
                {(source.function_name || source.function_id) && <> - <span>i18n:govoplan-access.function_fact.4f7435e4</span>: {source.function_name || source.function_id}</>}
                {(source.organization_unit_name || source.organization_unit_id) && <> - <span>i18n:govoplan-access.organization_unit.9832b383</span>: {source.organization_unit_name || source.organization_unit_id}</>}
              </div>
              <AccessExplanationLinks organizationHref={organizationHrefForSource(source)} idmHref={idmHrefForSource(source)} />
              <div className="admin-scope-list">{source.permissions.map((scope) => <code key={scope}>{scope}</code>)}</div>
            </div>)}
          </div> : <p className="muted small-note">i18n:govoplan-access.no_role_sources_found.91013aa5</p>}
          <h3>i18n:govoplan-access.function_facts.848b32cc</h3>
          {accessExplanation.function_facts.length ? <dl className="admin-details-grid">
            {accessExplanation.function_facts.map((fact) => <div key={fact.assignment_id}>
              <dt>{fact.function_name || fact.function_id}</dt>
              <dd>
                <span>i18n:govoplan-access.organization_unit.9832b383</span>: {fact.organization_unit_name || fact.organization_unit_id}<br />
                <span>i18n:govoplan-access.assignment_source.5fac1f72</span>: {fact.assignment_source}<br />
                <span>i18n:govoplan-access.mapped_roles.504d9ff9</span>: {factRoles(fact)}
                <AccessExplanationLinks organizationHref={organizationHrefForFact(fact)} idmHref={idmHrefForFact(fact)} />
              </dd>
            </div>)}
          </dl> : <p className="muted small-note">i18n:govoplan-access.no_function_facts_found.b2ecee17</p>}
          <h3>i18n:govoplan-access.effective_permissions.17c0fe8a</h3>
          <div className="admin-scope-list">
            {accessExplanation.scopes.map((scope) => <code key={scope.scope} title={scope.sources.map((source) => source.role_name).join(", ")}>{scope.scope}</code>)}
          </div>
        </>}
      </Dialog>

      <Dialog open={Boolean(temporaryPassword)} title="i18n:govoplan-access.temporary_password.62d60628" onClose={() => setTemporaryPassword(null)} className="admin-dialog" footer={<Button variant="primary" onClick={() => setTemporaryPassword(null)}>i18n:govoplan-access.i_have_recorded_it.7522da18</Button>}>
        {temporaryPassword && <><p>i18n:govoplan-access.this_is_shown_once_for.b0f0f526 <strong>{temporaryPassword.email}</strong>.</p><code className="admin-secret">{temporaryPassword.password}</code><p className="muted small-note">i18n:govoplan-access.transmit_it_through_a_separate_secure_channel.ab892c7b</p></>}
      </Dialog>

      <ConfirmDialog open={Boolean(deactivating)} title="i18n:govoplan-access.deactivate_tenant_membership.bbe33c9c" message={i18nMessage("i18n:govoplan-access.deactivate_value_in_the_active_tenant_historical.b91da381", { value0: deactivating?.email })} confirmLabel="i18n:govoplan-access.deactivate_user.9ddc7096" tone="danger" busy={busy} onCancel={() => setDeactivating(null)} onConfirm={() => void deactivate()} />
    </>);

}

function draftKey(draft: typeof emptyDraft): string {
  return JSON.stringify(draft);
}

function sortUsers(left: UserAdminItem, right: UserAdminItem): number {
  return (left.display_name || left.email).localeCompare(right.display_name || right.email) || left.email.localeCompare(right.email);
}

function sortGroups(left: GroupSummary, right: GroupSummary): number {
  return left.name.localeCompare(right.name);
}

function sortTenantRoles(left: RoleSummary, right: RoleSummary): number {
  const builtinDelta = Number(right.is_builtin) - Number(left.is_builtin);
  if (builtinDelta !== 0) return builtinDelta;
  return left.name.localeCompare(right.name);
}

function sourceKey(source: AccessRoleSourceItem): string {
  return [
    source.source_type,
    source.role_id,
    source.group_id || "",
    source.function_assignment_id || "",
    source.function_id || ""
  ].join(":");
}

function AccessExplanationLinks({ organizationHref, idmHref }: { organizationHref: string | null; idmHref: string | null }) {
  if (!organizationHref && !idmHref) return null;
  return (
    <div className="muted small-note">
      {organizationHref && <a href={organizationHref} title="i18n:govoplan-access.open_organizations">i18n:govoplan-access.open_organizations</a>}
      {organizationHref && idmHref && <span> | </span>}
      {idmHref && <a href={idmHref} title="i18n:govoplan-access.open_idm_assignment">i18n:govoplan-access.open_idm_assignment</a>}
    </div>
  );
}

function organizationHrefForSource(source: AccessRoleSourceItem): string | null {
  return organizationHref(source.function_id, source.organization_unit_id);
}

function organizationHrefForFact(fact: FunctionFactExplanationItem): string | null {
  return organizationHref(fact.function_id, fact.organization_unit_id);
}

function organizationHref(functionId?: string | null, unitId?: string | null): string | null {
  const params = new URLSearchParams();
  if (functionId) {
    params.set("section", "functions");
    params.set("function_id", functionId);
    if (unitId) params.set("unit_id", unitId);
  } else if (unitId) {
    params.set("section", "units");
    params.set("unit_id", unitId);
  }
  const query = params.toString();
  return query ? `/organizations?${query}` : null;
}

function idmHrefForSource(source: AccessRoleSourceItem): string | null {
  return idmHref(source.function_assignment_id, source.function_id);
}

function idmHrefForFact(fact: FunctionFactExplanationItem): string | null {
  return idmHref(fact.assignment_id, fact.function_id);
}

function idmHref(assignmentId?: string | null, functionId?: string | null): string | null {
  const params = new URLSearchParams();
  if (assignmentId) params.set("assignment_id", assignmentId);
  if (functionId) params.set("function_id", functionId);
  const query = params.toString();
  return query ? `/idm?${query}` : null;
}

function sourceTypeLabel(source: AccessRoleSourceItem): string {
  switch (source.source_type) {
    case "direct_role":
      return "i18n:govoplan-access.direct_role_source.bf3e6a27";
    case "group_role":
      return "i18n:govoplan-access.group_role_source.0aa38904";
    case "legacy_function_role":
      return "i18n:govoplan-access.legacy_function_role_source.36f81c6b";
    case "idm_function_role":
      return "i18n:govoplan-access.idm_function_role_source.14a231fe";
    case "system_role":
      return "i18n:govoplan-access.system_role_source.c6e83223";
    default:
      return source.source_type;
  }
}

function factRoles(fact: FunctionFactExplanationItem): string {
  return fact.role_names.length ? fact.role_names.join(", ") : "i18n:govoplan-access.no_mapped_roles.986bfb44";
}
