'use client';
/**
 * RBAC roles grid (f15) — **DEFERRED-IF-MISSING.** The b15 contract does not yet expose role grant/revoke
 * endpoints, so this console is served by the admin **mock** (REQ-031); an info banner says so. When the
 * endpoints land, only `services/admin/apis` flips — this screen is unchanged.
 *
 * Grants/revokes are gated on `canManageRoles` (only a `super_admin`); the server remains the authority. The
 * grid lists **active** grants (revoked rows are filtered out); an audited confirm dialog fronts every
 * revoke and grant.
 */
import { useState } from 'react';
import { useLocale, useTranslations } from 'next-intl';
import { useSnackbar } from 'notistack';
import {
  Box,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
  MenuItem,
  Skeleton,
  Stack,
  TextField,
} from '@mui/material';
import { AppAlert, AppButton } from '@/components';
import {
  AdminDataTable,
  AdminEmptyState,
  AdminErrorState,
  AdminPageHeader,
  ConfirmDialog,
  type AdminTableColumn,
} from '@/components/admin';
import { formatShamsiDate } from '@/utils';
import { useAdminCapabilities } from '@/hooks';
import type { AdminRole, RoleGrant } from '@/services/admin/types';
import { useAdminRoles, useGrantRole, useRevokeRole } from '@/services/admin';

/** The fine-grained admin roles the grid grants (aligned with the b2 `AdminRole` enum). */
const ROLES: readonly AdminRole[] = ['super_admin', 'admin', 'support', 'finance', 'moderation'];

export default function AdminRolesPage() {
  const t = useTranslations('admin');
  const locale = useLocale();
  const caps = useAdminCapabilities();
  const { enqueueSnackbar } = useSnackbar();

  const roles = useAdminRoles();
  const revoke = useRevokeRole();

  const [granting, setGranting] = useState(false);
  const [revoking, setRevoking] = useState<RoleGrant | null>(null);

  // Only active grants — a revoked grant leaves the grid.
  const active = (roles.data ?? []).filter((g) => g.revokedAt == null);

  const columns: AdminTableColumn<RoleGrant>[] = [
    { key: 'user', header: t('role_col_user'), render: (g) => `#${g.userId}` },
    {
      key: 'role',
      header: t('role_col_role'),
      render: (g) => <Chip size="small" variant="outlined" label={t(`role_${g.role}`)} />,
    },
    { key: 'granted', header: t('role_col_granted'), render: (g) => formatShamsiDate(g.grantedAt, locale) },
    ...(caps.canManageRoles
      ? [
          {
            key: 'actions',
            header: '',
            align: 'right',
            render: (g: RoleGrant) => (
              <AppButton variant="text" color="error" startIcon="delete" onClick={() => setRevoking(g)}>
                {t('role_revoke')}
              </AppButton>
            ),
          } as AdminTableColumn<RoleGrant>,
        ]
      : []),
  ];

  const onRevokeConfirm = () => {
    if (!revoking) return;
    revoke.mutate(
      { userId: revoking.userId, role: revoking.role },
      {
        onSuccess: () => {
          enqueueSnackbar(t('role_updated'), { variant: 'success' });
          setRevoking(null);
        },
      },
    );
  };

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <AdminPageHeader
        title={t('role_title')}
        subtitle={t('role_subtitle')}
        actions={
          caps.canManageRoles ? (
            <AppButton variant="contained" color="primary" startIcon="add" onClick={() => setGranting(true)}>
              {t('role_grant')}
            </AppButton>
          ) : undefined
        }
      />

      <AppAlert severity="info" variant="outlined">
        {t('role_deferred')}
      </AppAlert>

      {roles.isLoading ? (
        <Skeleton variant="rounded" height={200} />
      ) : roles.isError ? (
        <AdminErrorState message={t('error_generic')} retryLabel={t('retry')} onRetry={() => roles.refetch()} />
      ) : active.length === 0 ? (
        <AdminEmptyState icon="roles" title={t('role_title')} />
      ) : (
        <AdminDataTable
          columns={columns}
          rows={active}
          getRowKey={(g) => `${g.userId}:${g.role}`}
          ariaLabel={t('role_title')}
        />
      )}

      {granting ? <GrantRoleDialog onClose={() => setGranting(false)} /> : null}

      <ConfirmDialog
        open={revoking != null}
        title={t('role_revoke')}
        body={revoking ? t('role_revoke_confirm', { role: t(`role_${revoking.role}`), id: revoking.userId }) : undefined}
        confirmLabel={t('role_revoke')}
        cancelLabel={t('cancel')}
        confirmColor="error"
        loading={revoke.isPending}
        onConfirm={onRevokeConfirm}
        onClose={() => setRevoking(null)}
      />
    </Box>
  );
}

/** Collect a target user id + a role, then grant it (inline confirm copy once both are set). */
function GrantRoleDialog({ onClose }: { onClose: () => void }) {
  const t = useTranslations('admin');
  const { enqueueSnackbar } = useSnackbar();
  const grant = useGrantRole();

  const [userId, setUserId] = useState('');
  const [role, setRole] = useState<AdminRole>('support');

  const parsedId = Number(userId);
  const valid = /^\d+$/.test(userId.trim()) && parsedId > 0;

  const onGrant = () => {
    if (!valid) return;
    grant.mutate(
      { userId: parsedId, role },
      {
        onSuccess: () => {
          enqueueSnackbar(t('role_updated'), { variant: 'success' });
          onClose();
        },
      },
    );
  };

  return (
    <Dialog open onClose={grant.isPending ? undefined : onClose} fullWidth maxWidth="xs">
      <DialogTitle sx={{ fontWeight: 800 }}>{t('role_grant')}</DialogTitle>
      <DialogContent>
        <Stack sx={{ gap: 2, mt: 1 }}>
          <TextField
            label={t('role_col_user')}
            type="number"
            value={userId}
            onChange={(e) => setUserId(e.target.value)}
            slotProps={{ htmlInput: { min: 1 } }}
          />
          <TextField select label={t('role_col_role')} value={role} onChange={(e) => setRole(e.target.value as AdminRole)}>
            {ROLES.map((r) => (
              <MenuItem key={r} value={r}>
                {t(`role_${r}`)}
              </MenuItem>
            ))}
          </TextField>
          {valid ? (
            <DialogContentText>{t('role_grant_confirm', { role: t(`role_${role}`), id: parsedId })}</DialogContentText>
          ) : null}
        </Stack>
      </DialogContent>
      <DialogActions sx={{ px: 3, pb: 2 }}>
        <AppButton variant="text" color="inherit" onClick={onClose} disabled={grant.isPending}>
          {t('cancel')}
        </AppButton>
        <AppButton variant="contained" color="primary" onClick={onGrant} disabled={!valid || grant.isPending}>
          {grant.isPending ? t('saving') : t('confirm')}
        </AppButton>
      </DialogActions>
    </Dialog>
  );
}
