import { useMemo, useState, type FormEvent, type ReactNode } from 'react';
import { Building2, CircleDollarSign, KeyRound, Pencil, Plus, RotateCcw, Trash2, UserRound, UsersRound } from 'lucide-react';
import type {
  GatewayTenant,
  GatewayTenantUpsertRequest,
  GatewayUser,
  GatewayUserUpsertRequest,
  GatewayWalletAccount,
  UserGroup,
  UserGroupUpsertRequest,
  WalletRechargeRequest,
} from '@easyai-ai-gateway/contracts';
import {
  Badge,
  Button,
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  ConfirmDialog,
  FormDialog,
  Input,
  Label,
  ScreenMessage,
  Select,
  Table,
  TableCell,
  TableHead,
  TableRow,
  Textarea,
} from '../../components/ui';
import type { ConsoleData } from '../../app-state';
import type { LoadState } from '../../types';

type TenantForm = {
  tenantKey: string;
  source: string;
  externalTenantId: string;
  name: string;
  description: string;
  defaultUserGroupId: string;
  planKey: string;
  billingProfileJson: string;
  rateLimitPolicyJson: string;
  authPolicyJson: string;
  metadataJson: string;
  status: string;
};

type UserForm = {
  userKey: string;
  source: string;
  externalUserId: string;
  username: string;
  displayName: string;
  email: string;
  phone: string;
  avatarUrl: string;
  password: string;
  gatewayTenantId: string;
  tenantId: string;
  tenantKey: string;
  defaultUserGroupId: string;
  roles: string;
  authProfileJson: string;
  metadataJson: string;
  status: string;
};

type WalletForm = {
  currency: string;
  amount: string;
  reason: string;
};

type UserGroupForm = {
  groupKey: string;
  name: string;
  description: string;
  source: string;
  priority: string;
  rechargeDiscountFactor: string;
  rechargeDiscountPolicy: Record<string, unknown>;
  billingDiscountFactor: string;
  billingDiscountPolicy: Record<string, unknown>;
  rateLimitPolicyJson: string;
  quotaPolicyJson: string;
  metadataJson: string;
  status: string;
};

const tenantStatuses = ['active', 'disabled', 'locked'];
const userStatuses = ['active', 'disabled', 'locked'];
const userGroupStatuses = ['active', 'disabled'];
const sourceOptions = ['gateway', 'server-main', 'sync'];
const roleOptions = [
  { label: '普通用户', value: 'user' },
  { label: '创作者', value: 'creator' },
  { label: '管理', value: 'operator' },
  { label: '超级管理员', value: 'manager' },
  { label: '管理员', value: 'admin' },
];

export function TenantsPanel(props: IdentityPanelProps) {
  const [dialogOpen, setDialogOpen] = useState(false);
  const [editingId, setEditingId] = useState('');
  const [form, setForm] = useState<TenantForm>(() => defaultTenantForm());
  const [localError, setLocalError] = useState('');
  const [pendingDeleteTenant, setPendingDeleteTenant] = useState<GatewayTenant | null>(null);

  function openCreateDialog() {
    setEditingId('');
    setLocalError('');
    setForm(defaultTenantForm());
    setDialogOpen(true);
  }

  function editTenant(tenant: GatewayTenant) {
    setEditingId(tenant.id);
    setLocalError('');
    setForm(tenantToForm(tenant));
    setDialogOpen(true);
  }

  function closeDialog() {
    setDialogOpen(false);
    setEditingId('');
    setLocalError('');
  }

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setLocalError('');
    try {
      await props.onSaveTenant(formToTenantPayload(form), editingId || undefined);
      closeDialog();
    } catch (err) {
      setLocalError(err instanceof Error ? err.message : '保存租户失败');
    }
  }

  async function deleteTenant(tenant: GatewayTenant) {
    try {
      await props.onDeleteTenant(tenant.id);
      setPendingDeleteTenant(null);
    } catch (err) {
      setLocalError(err instanceof Error ? err.message : '删除租户失败');
    }
  }

  return (
    <div className="pageStack">
      <ScreenMessage message={identityLocalErrorMessage(localError, props)} variant="error" duration={0} onClose={() => setLocalError('')} />
      <IdentityHeader
        count={props.data.tenants.length}
        description="租户可独立维护，也可承载 server-main 同步过来的租户标识。"
        icon={<Building2 size={17} />}
        message={identityHeaderMessage(props)}
        title="租户管理"
        actionLabel="新增租户"
        onCreate={openCreateDialog}
      />
      {props.data.tenants.length ? (
        <Table className="identityDataTable tenantTable">
          <TableRow>
            <TableHead>租户</TableHead>
            <TableHead>来源</TableHead>
            <TableHead>默认用户组</TableHead>
            <TableHead>套餐</TableHead>
            <TableHead>状态</TableHead>
            <TableHead>操作</TableHead>
          </TableRow>
          {props.data.tenants.map((tenant) => (
            <TableRow key={tenant.id}>
              <TableCell><IdentityName title={tenant.name} subtitle={tenant.tenantKey} /></TableCell>
              <TableCell>{tenant.source}</TableCell>
              <TableCell>{groupName(props.data.userGroups, tenant.defaultUserGroupId)}</TableCell>
              <TableCell>{tenant.planKey || '未设置'}</TableCell>
              <TableCell><Badge variant={tenant.status === 'active' ? 'success' : 'secondary'}>{tenant.status}</Badge></TableCell>
              <TableCell><TableActions onEdit={() => editTenant(tenant)} onDelete={() => setPendingDeleteTenant(tenant)} /></TableCell>
            </TableRow>
          ))}
        </Table>
      ) : (
        <EmptyIdentity title="暂无租户" description="点击新增租户建立本地租户闭环。" />
      )}

      <FormDialog
        ariaLabel={editingId ? '编辑租户' : '新增租户'}
        className="identityDialog"
        eyebrow={editingId ? 'Edit Tenant' : 'New Tenant'}
        footer={<DialogFooter editing={Boolean(editingId)} loading={props.state === 'loading'} onCancel={closeDialog} />}
        open={dialogOpen}
        title={editingId ? '编辑租户' : '新增租户'}
        onClose={closeDialog}
        onSubmit={submit}
      >
        <Label>租户 Key<Input size="sm" value={form.tenantKey} onChange={(event) => setForm({ ...form, tenantKey: event.target.value })} placeholder="default" /></Label>
        <Label>租户名称<Input size="sm" value={form.name} onChange={(event) => setForm({ ...form, name: event.target.value })} placeholder="默认租户" /></Label>
        <Label>来源<Select size="sm" value={form.source} onChange={(event) => setForm({ ...form, source: event.target.value })}>{sourceOptions.map(option)}</Select></Label>
        <Label>状态<Select size="sm" value={form.status} onChange={(event) => setForm({ ...form, status: event.target.value })}>{tenantStatuses.map(option)}</Select></Label>
        <Label>外部租户 ID<Input size="sm" value={form.externalTenantId} onChange={(event) => setForm({ ...form, externalTenantId: event.target.value })} placeholder="server-main tenant id" /></Label>
        <Label>套餐 Key<Input size="sm" value={form.planKey} onChange={(event) => setForm({ ...form, planKey: event.target.value })} placeholder="free / pro" /></Label>
        <Label className="spanTwo">默认用户组<Select size="sm" value={form.defaultUserGroupId} onChange={(event) => setForm({ ...form, defaultUserGroupId: event.target.value })}><option value="">未设置</option>{props.data.userGroups.map((group) => <option value={group.id} key={group.id}>{group.name}</option>)}</Select></Label>
        <Label className="spanTwo">描述<Input size="sm" value={form.description} onChange={(event) => setForm({ ...form, description: event.target.value })} placeholder="内部备注" /></Label>
        <JsonField label="计费资料 JSON" value={form.billingProfileJson} onChange={(value) => setForm({ ...form, billingProfileJson: value })} />
        <JsonField label="限流策略 JSON" value={form.rateLimitPolicyJson} onChange={(value) => setForm({ ...form, rateLimitPolicyJson: value })} />
        <JsonField label="授权策略 JSON" value={form.authPolicyJson} onChange={(value) => setForm({ ...form, authPolicyJson: value })} />
        <JsonField label="元数据 JSON" value={form.metadataJson} onChange={(value) => setForm({ ...form, metadataJson: value })} />
      </FormDialog>
      <ConfirmDialog
        confirmLabel="删除租户"
        description="租户会被软删除，关联用户不会被自动删除。"
        loading={props.state === 'loading'}
        open={Boolean(pendingDeleteTenant)}
        title={`确认删除租户 ${pendingDeleteTenant?.name ?? ''}？`}
        onCancel={() => setPendingDeleteTenant(null)}
        onConfirm={() => pendingDeleteTenant ? deleteTenant(pendingDeleteTenant) : undefined}
      />
    </div>
  );
}

export function UsersPanel(props: IdentityPanelProps) {
  const [dialogOpen, setDialogOpen] = useState(false);
  const [editingId, setEditingId] = useState('');
  const [form, setForm] = useState<UserForm>(() => defaultUserForm(props.data.tenants[0]));
  const [localError, setLocalError] = useState('');
  const [pendingDeleteUser, setPendingDeleteUser] = useState<GatewayUser | null>(null);
  const [walletUser, setWalletUser] = useState<GatewayUser | null>(null);
  const [walletForm, setWalletForm] = useState<WalletForm>(() => defaultWalletForm());

  const tenantById = useMemo(() => new Map(props.data.tenants.map((tenant) => [tenant.id, tenant])), [props.data.tenants]);

  function openCreateDialog() {
    setEditingId('');
    setLocalError('');
    setForm(defaultUserForm(props.data.tenants[0]));
    setDialogOpen(true);
  }

  function editUser(user: GatewayUser) {
    setEditingId(user.id);
    setLocalError('');
    setForm(userToForm(user));
    setDialogOpen(true);
  }

  function closeDialog() {
    setDialogOpen(false);
    setEditingId('');
    setLocalError('');
  }

  function openWalletDialog(user: GatewayUser) {
    const wallet = primaryWallet(user);
    setLocalError('');
    setWalletUser(user);
    setWalletForm({
      currency: wallet?.currency ?? 'resource',
      amount: '',
      reason: defaultRechargeReason,
    });
  }

  function closeWalletDialog() {
    setWalletUser(null);
    setWalletForm(defaultWalletForm());
  }

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setLocalError('');
    try {
      await props.onSaveUser(formToUserPayload(form), editingId || undefined);
      closeDialog();
    } catch (err) {
      setLocalError(err instanceof Error ? err.message : '保存用户失败');
    }
  }

  async function deleteUser(user: GatewayUser) {
    try {
      await props.onDeleteUser(user.id);
      setPendingDeleteUser(null);
    } catch (err) {
      setLocalError(err instanceof Error ? err.message : '删除用户失败');
    }
  }

  async function submitWallet(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setLocalError('');
    if (!walletUser) return;
    const amount = Number(walletForm.amount);
    if (!Number.isFinite(amount) || amount <= 0) {
      setLocalError('充值金额必须大于 0');
      return;
    }
    if (!walletForm.reason.trim()) {
      setLocalError('请填写调整原因');
      return;
    }
    try {
      await props.onRechargeUserWalletBalance(walletUser.id, {
        currency: walletForm.currency,
        amount,
        reason: walletForm.reason.trim(),
        idempotencyKey: newIdempotencyKey(),
      });
      closeWalletDialog();
    } catch (err) {
      setLocalError(err instanceof Error ? err.message : '充值用户余额失败');
    }
  }

  function selectTenant(gatewayTenantId: string) {
    const tenant = tenantById.get(gatewayTenantId);
    setForm({ ...form, gatewayTenantId, tenantKey: tenant?.tenantKey ?? form.tenantKey });
  }

  return (
    <div className="pageStack">
      <ScreenMessage message={identityLocalErrorMessage(localError, props)} variant="error" duration={0} onClose={() => setLocalError('')} />
      <IdentityHeader
        count={props.data.users.length}
        description="支持本地用户闭环，也保留 server-main 用户同步字段。"
        icon={<UserRound size={17} />}
        message={identityHeaderMessage(props)}
        title="用户管理"
        actionLabel="新增用户"
        onCreate={openCreateDialog}
      />
      {props.data.users.length ? (
        <Table className="identityDataTable userTable">
          <TableRow>
            <TableHead>用户</TableHead>
            <TableHead>角色</TableHead>
            <TableHead>租户</TableHead>
            <TableHead>用户组</TableHead>
            <TableHead>余额</TableHead>
            <TableHead>来源</TableHead>
            <TableHead>状态</TableHead>
            <TableHead>操作</TableHead>
          </TableRow>
          {props.data.users.map((user) => (
            <TableRow key={user.id}>
              <TableCell><IdentityName title={user.displayName || user.username} subtitle={user.email || user.username} /></TableCell>
              <TableCell>{roleLabel(user.roles)}</TableCell>
              <TableCell>{tenantName(props.data.tenants, user.gatewayTenantId, user.tenantKey)}</TableCell>
              <TableCell>{groupName(props.data.userGroups, user.defaultUserGroupId)}</TableCell>
              <TableCell>{walletSummary(user)}</TableCell>
              <TableCell>{user.source}</TableCell>
              <TableCell><Badge variant={user.status === 'active' ? 'success' : 'secondary'}>{user.status}</Badge></TableCell>
              <TableCell><TableActions onEdit={() => editUser(user)} onDelete={() => setPendingDeleteUser(user)} onWallet={() => openWalletDialog(user)} /></TableCell>
            </TableRow>
          ))}
        </Table>
      ) : (
        <EmptyIdentity title="暂无用户" description="可先添加本地用户，后续再与 server-main 同步关系对齐。" />
      )}

      <FormDialog
        ariaLabel={editingId ? '编辑用户' : '新增用户'}
        className="identityDialog"
        eyebrow={editingId ? 'Edit User' : 'New User'}
        footer={<DialogFooter editing={Boolean(editingId)} loading={props.state === 'loading'} onCancel={closeDialog} />}
        open={dialogOpen}
        title={editingId ? '编辑用户' : '新增用户'}
        onClose={closeDialog}
        onSubmit={submit}
      >
        <Label>用户名<Input size="sm" value={form.username} onChange={(event) => setForm({ ...form, username: event.target.value })} placeholder="user@example.com" /></Label>
        <Label>用户 Key<Input size="sm" value={form.userKey} onChange={(event) => setForm({ ...form, userKey: event.target.value })} placeholder="留空自动生成" /></Label>
        <Label>显示名称<Input size="sm" value={form.displayName} onChange={(event) => setForm({ ...form, displayName: event.target.value })} placeholder="王小明" /></Label>
        <Label>邮箱<Input size="sm" value={form.email} onChange={(event) => setForm({ ...form, email: event.target.value })} placeholder="name@example.com" /></Label>
        <Label>手机号<Input size="sm" value={form.phone} onChange={(event) => setForm({ ...form, phone: event.target.value })} /></Label>
        <Label>头像 URL<Input size="sm" value={form.avatarUrl} onChange={(event) => setForm({ ...form, avatarUrl: event.target.value })} /></Label>
        <Label>来源<Select size="sm" value={form.source} onChange={(event) => setForm({ ...form, source: event.target.value })}>{sourceOptions.map(option)}</Select></Label>
        <Label>状态<Select size="sm" value={form.status} onChange={(event) => setForm({ ...form, status: event.target.value })}>{userStatuses.map(option)}</Select></Label>
        <Label>租户<Select size="sm" value={form.gatewayTenantId} onChange={(event) => selectTenant(event.target.value)}><option value="">未设置</option>{props.data.tenants.map((tenant) => <option value={tenant.id} key={tenant.id}>{tenant.name}</option>)}</Select></Label>
        <Label>租户 Key<Input size="sm" value={form.tenantKey} onChange={(event) => setForm({ ...form, tenantKey: event.target.value })} /></Label>
        <Label>外部用户 ID<Input size="sm" value={form.externalUserId} onChange={(event) => setForm({ ...form, externalUserId: event.target.value })} /></Label>
        <Label>业务租户 ID<Input size="sm" value={form.tenantId} onChange={(event) => setForm({ ...form, tenantId: event.target.value })} /></Label>
        <Label>默认用户组<Select size="sm" value={form.defaultUserGroupId} onChange={(event) => setForm({ ...form, defaultUserGroupId: event.target.value })}><option value="">未设置</option>{props.data.userGroups.map((group) => <option value={group.id} key={group.id}>{group.name}</option>)}</Select></Label>
        <Label>登录密码<Input size="sm" value={form.password} type="password" onChange={(event) => setForm({ ...form, password: event.target.value })} placeholder={editingId ? '留空不修改' : '可为空'} /></Label>
        <Label>
          角色
          <Select size="sm" value={form.roles} onChange={(event) => setForm({ ...form, roles: event.target.value })}>
            {roleOptions.map((role) => <option value={role.value} key={role.value}>{role.label}</option>)}
          </Select>
        </Label>
        <JsonField label="授权资料 JSON" value={form.authProfileJson} onChange={(value) => setForm({ ...form, authProfileJson: value })} />
        <JsonField label="元数据 JSON" value={form.metadataJson} onChange={(value) => setForm({ ...form, metadataJson: value })} />
      </FormDialog>
      <ConfirmDialog
        confirmLabel="删除用户"
        description="用户会被软删除，已创建的任务记录会保留。"
        loading={props.state === 'loading'}
        open={Boolean(pendingDeleteUser)}
        title={`确认删除用户 ${pendingDeleteUser?.username ?? ''}？`}
        onCancel={() => setPendingDeleteUser(null)}
        onConfirm={() => pendingDeleteUser ? deleteUser(pendingDeleteUser) : undefined}
      />
      <FormDialog
        ariaLabel="充值用户余额"
        className="identityDialog walletDialog"
        eyebrow="Wallet Adjustment"
        footer={<WalletDialogFooter loading={props.state === 'loading'} onCancel={closeWalletDialog} />}
        open={Boolean(walletUser)}
        title={`充值余额${walletUser ? ` · ${walletUser.displayName || walletUser.username}` : ''}`}
        onClose={closeWalletDialog}
        onSubmit={submitWallet}
      >
        <Label>币种<Input size="sm" value={walletForm.currency} onChange={(event) => setWalletForm({ ...walletForm, currency: event.target.value })} placeholder="resource" /></Label>
        <Label>充值金额<Input size="sm" value={walletForm.amount} inputMode="decimal" onChange={(event) => setWalletForm({ ...walletForm, amount: event.target.value })} placeholder="100" /></Label>
        <Label className="spanTwo">当前余额<Input size="sm" value={walletUser ? walletSummary(walletUser) : '0 resource'} disabled /></Label>
        <Label className="spanTwo">充值原因<Textarea size="sm" rows={3} value={walletForm.reason} onChange={(event) => setWalletForm({ ...walletForm, reason: event.target.value })} placeholder="例如：线下充值确认 / 客服补偿 / 账务修正" /></Label>
      </FormDialog>
    </div>
  );
}

export function UserGroupsPanel(props: IdentityPanelProps) {
  const [dialogOpen, setDialogOpen] = useState(false);
  const [editingId, setEditingId] = useState('');
  const [form, setForm] = useState<UserGroupForm>(() => defaultUserGroupForm());
  const [localError, setLocalError] = useState('');
  const [pendingDeleteGroup, setPendingDeleteGroup] = useState<UserGroup | null>(null);

  function openCreateDialog() {
    setEditingId('');
    setLocalError('');
    setForm(defaultUserGroupForm());
    setDialogOpen(true);
  }

  function editGroup(group: UserGroup) {
    setEditingId(group.id);
    setLocalError('');
    setForm(userGroupToForm(group));
    setDialogOpen(true);
  }

  function closeDialog() {
    setDialogOpen(false);
    setEditingId('');
    setLocalError('');
  }

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setLocalError('');
    try {
      await props.onSaveUserGroup(formToUserGroupPayload(form), editingId || undefined);
      closeDialog();
    } catch (err) {
      setLocalError(err instanceof Error ? err.message : '保存用户组失败');
    }
  }

  async function deleteGroup(group: UserGroup) {
    try {
      await props.onDeleteUserGroup(group.id);
      setPendingDeleteGroup(null);
    } catch (err) {
      setLocalError(err instanceof Error ? err.message : '删除用户组失败');
    }
  }

  return (
    <div className="pageStack">
      <ScreenMessage message={identityLocalErrorMessage(localError, props)} variant="error" duration={0} onClose={() => setLocalError('')} />
      <IdentityHeader
        count={props.data.userGroups.length}
        description="用户组承载充值折扣、计费折扣、限流和额度策略。"
        icon={<UsersRound size={17} />}
        message={identityHeaderMessage(props)}
        title="用户组管理"
        actionLabel="新增用户组"
        onCreate={openCreateDialog}
      />
      {props.data.userGroups.length ? (
        <Table className="identityDataTable groupTable">
          <TableRow>
            <TableHead>用户组</TableHead>
            <TableHead>来源</TableHead>
            <TableHead>优先级</TableHead>
            <TableHead>折扣</TableHead>
            <TableHead>限流</TableHead>
            <TableHead>状态</TableHead>
            <TableHead>操作</TableHead>
          </TableRow>
          {props.data.userGroups.map((group) => (
            <TableRow key={group.id}>
              <TableCell><IdentityName title={group.name} subtitle={group.groupKey} /></TableCell>
              <TableCell>{group.source}</TableCell>
              <TableCell>{group.priority}</TableCell>
              <TableCell>{discountSummary(group)}</TableCell>
              <TableCell>{policyKeys(group.rateLimitPolicy).join(', ') || '未设置'}</TableCell>
              <TableCell><Badge variant={group.status === 'active' ? 'success' : 'secondary'}>{group.status}</Badge></TableCell>
              <TableCell><TableActions onEdit={() => editGroup(group)} onDelete={() => setPendingDeleteGroup(group)} /></TableCell>
            </TableRow>
          ))}
        </Table>
      ) : (
        <EmptyIdentity title="暂无用户组" description="可先新增默认用户组，用来配置折扣和并发控制。" />
      )}

      <FormDialog
        ariaLabel={editingId ? '编辑用户组' : '新增用户组'}
        className="identityDialog"
        eyebrow={editingId ? 'Edit User Group' : 'New User Group'}
        footer={<DialogFooter editing={Boolean(editingId)} loading={props.state === 'loading'} onCancel={closeDialog} />}
        open={dialogOpen}
        title={editingId ? '编辑用户组' : '新增用户组'}
        onClose={closeDialog}
        onSubmit={submit}
      >
        <Label>用户组 Key<Input size="sm" value={form.groupKey} onChange={(event) => setForm({ ...form, groupKey: event.target.value })} placeholder="default" /></Label>
        <Label>名称<Input size="sm" value={form.name} onChange={(event) => setForm({ ...form, name: event.target.value })} placeholder="默认用户组" /></Label>
        <Label>来源<Select size="sm" value={form.source} onChange={(event) => setForm({ ...form, source: event.target.value })}>{sourceOptions.map(option)}</Select></Label>
        <Label>状态<Select size="sm" value={form.status} onChange={(event) => setForm({ ...form, status: event.target.value })}>{userGroupStatuses.map(option)}</Select></Label>
        <Label>优先级<Input size="sm" value={form.priority} inputMode="numeric" onChange={(event) => setForm({ ...form, priority: event.target.value })} /></Label>
        <Label className="spanTwo">描述<Input size="sm" value={form.description} onChange={(event) => setForm({ ...form, description: event.target.value })} /></Label>
        <Label>充值折扣系数<Input size="sm" value={form.rechargeDiscountFactor} inputMode="decimal" placeholder="1 = 不打折，0.95 = 95 折" onChange={(event) => setForm({ ...form, rechargeDiscountFactor: event.target.value })} /></Label>
        <Label>计费折扣系数<Input size="sm" value={form.billingDiscountFactor} inputMode="decimal" placeholder="1 = 不打折，0.95 = 95 折" onChange={(event) => setForm({ ...form, billingDiscountFactor: event.target.value })} /></Label>
        <JsonField label="限流策略 JSON" value={form.rateLimitPolicyJson} onChange={(value) => setForm({ ...form, rateLimitPolicyJson: value })} />
        <JsonField label="额度策略 JSON" value={form.quotaPolicyJson} onChange={(value) => setForm({ ...form, quotaPolicyJson: value })} />
        <JsonField label="元数据 JSON" value={form.metadataJson} onChange={(value) => setForm({ ...form, metadataJson: value })} />
      </FormDialog>
      <ConfirmDialog
        confirmLabel="删除用户组"
        description="删除后租户和用户上引用该用户组的默认策略会失效。"
        loading={props.state === 'loading'}
        open={Boolean(pendingDeleteGroup)}
        title={`确认删除用户组 ${pendingDeleteGroup?.name ?? ''}？`}
        onCancel={() => setPendingDeleteGroup(null)}
        onConfirm={() => pendingDeleteGroup ? deleteGroup(pendingDeleteGroup) : undefined}
      />
    </div>
  );
}

type IdentityPanelProps = {
  data: ConsoleData;
  operationMessage: string;
  state: LoadState;
  onDeleteTenant: (tenantId: string) => Promise<void>;
  onDeleteUser: (userId: string) => Promise<void>;
  onDeleteUserGroup: (groupId: string) => Promise<void>;
  onSaveTenant: (input: GatewayTenantUpsertRequest, tenantId?: string) => Promise<void>;
  onSaveUser: (input: GatewayUserUpsertRequest, userId?: string) => Promise<void>;
  onRechargeUserWalletBalance: (userId: string, input: WalletRechargeRequest) => Promise<void>;
  onSaveUserGroup: (input: UserGroupUpsertRequest, groupId?: string) => Promise<void>;
};

const defaultRechargeReason = '手动充值';

function identityHeaderMessage(props: Pick<IdentityPanelProps, 'operationMessage' | 'state'>) {
  return props.state === 'error' ? '' : props.operationMessage;
}

function identityLocalErrorMessage(localError: string, props: Pick<IdentityPanelProps, 'operationMessage' | 'state'>) {
  if (!localError) return '';
  if (props.state === 'error' && localError === props.operationMessage) return '';
  return localError;
}

function IdentityHeader(props: {
  actionLabel: string;
  count: number;
  description: string;
  icon: ReactNode;
  message?: string;
  title: string;
  onCreate: () => void;
}) {
  return (
    <Card>
      <CardHeader>
        <div className="identityHeaderTitle">
          <div className="iconBox">{props.icon}</div>
          <div>
            <CardTitle>{props.title}</CardTitle>
            <p className="mutedText">{props.description}</p>
          </div>
          <Badge variant="secondary">{props.count}</Badge>
        </div>
        <Button type="button" onClick={props.onCreate}><Plus size={15} />{props.actionLabel}</Button>
      </CardHeader>
      {props.message && <CardContent><p className="formMessage">{props.message}</p></CardContent>}
    </Card>
  );
}

function IdentityName(props: { title: string; subtitle: string }) {
  return (
    <span className="identityTableName">
      <strong>{props.title}</strong>
      <small>{props.subtitle}</small>
    </span>
  );
}

function TableActions(props: { onDelete: () => void; onEdit: () => void; onWallet?: () => void }) {
  return (
    <span className="tableActions">
      {props.onWallet && <Button type="button" variant="outline" size="icon" title="余额" onClick={props.onWallet}><CircleDollarSign size={14} /></Button>}
      <Button type="button" variant="outline" size="icon" title="修改" onClick={props.onEdit}><Pencil size={14} /></Button>
      <Button type="button" variant="destructive" size="icon" title="删除" onClick={props.onDelete}><Trash2 size={14} /></Button>
    </span>
  );
}

function EmptyIdentity(props: { title: string; description: string }) {
  return (
    <Card>
      <CardContent className="emptyState">
        <KeyRound size={18} />
        <strong>{props.title}</strong>
        <span>{props.description}</span>
      </CardContent>
    </Card>
  );
}

function DialogFooter(props: { editing: boolean; loading: boolean; onCancel: () => void }) {
  return (
    <>
      <Button type="button" variant="outline" onClick={props.onCancel}><RotateCcw size={15} />取消</Button>
      <Button type="submit" disabled={props.loading}>{props.editing ? <Pencil size={15} /> : <Plus size={15} />}{props.editing ? '保存修改' : '新增'}</Button>
    </>
  );
}

function WalletDialogFooter(props: { loading: boolean; onCancel: () => void }) {
  return (
    <>
      <Button type="button" variant="outline" onClick={props.onCancel}><RotateCcw size={15} />取消</Button>
      <Button type="submit" disabled={props.loading}><CircleDollarSign size={15} />确认充值</Button>
    </>
  );
}

function JsonField(props: { label: string; value: string; onChange: (value: string) => void }) {
  return (
    <Label className="spanTwo">
      {props.label}
      <Textarea size="sm" rows={3} value={props.value} placeholder='{"rules":[]}' onChange={(event) => props.onChange(event.target.value)} />
    </Label>
  );
}

function option(value: string) {
  return <option value={value} key={value}>{value}</option>;
}

function defaultTenantForm(): TenantForm {
  return {
    tenantKey: `tenant-${Date.now().toString(36)}`,
    source: 'gateway',
    externalTenantId: '',
    name: '默认租户',
    description: '',
    defaultUserGroupId: '',
    planKey: '',
    billingProfileJson: '{}',
    rateLimitPolicyJson: '{}',
    authPolicyJson: '{}',
    metadataJson: '{}',
    status: 'active',
  };
}

function tenantToForm(tenant: GatewayTenant): TenantForm {
  return {
    tenantKey: tenant.tenantKey,
    source: tenant.source,
    externalTenantId: tenant.externalTenantId ?? '',
    name: tenant.name,
    description: tenant.description ?? '',
    defaultUserGroupId: tenant.defaultUserGroupId ?? '',
    planKey: tenant.planKey ?? '',
    billingProfileJson: stringifyJson(tenant.billingProfile),
    rateLimitPolicyJson: stringifyJson(tenant.rateLimitPolicy),
    authPolicyJson: stringifyJson(tenant.authPolicy),
    metadataJson: stringifyJson(tenant.metadata),
    status: tenant.status,
  };
}

function formToTenantPayload(form: TenantForm): GatewayTenantUpsertRequest {
  return {
    tenantKey: form.tenantKey.trim(),
    source: form.source,
    externalTenantId: form.externalTenantId.trim() || undefined,
    name: form.name.trim(),
    description: form.description.trim() || undefined,
    defaultUserGroupId: form.defaultUserGroupId || undefined,
    planKey: form.planKey.trim() || undefined,
    billingProfile: parseJsonObject(form.billingProfileJson, '计费资料 JSON'),
    rateLimitPolicy: parseJsonObject(form.rateLimitPolicyJson, '限流策略 JSON'),
    authPolicy: parseJsonObject(form.authPolicyJson, '授权策略 JSON'),
    metadata: parseJsonObject(form.metadataJson, '元数据 JSON'),
    status: form.status,
  };
}

function defaultUserForm(tenant?: GatewayTenant): UserForm {
  return {
    userKey: '',
    source: 'gateway',
    externalUserId: '',
    username: '',
    displayName: '',
    email: '',
    phone: '',
    avatarUrl: '',
    password: '',
    gatewayTenantId: tenant?.id ?? '',
    tenantId: '',
    tenantKey: tenant?.tenantKey ?? '',
    defaultUserGroupId: '',
    roles: 'user',
    authProfileJson: '{}',
    metadataJson: '{}',
    status: 'active',
  };
}

function defaultWalletForm(): WalletForm {
  return {
    currency: 'resource',
    amount: '',
    reason: defaultRechargeReason,
  };
}

function userToForm(user: GatewayUser): UserForm {
  return {
    userKey: user.userKey,
    source: user.source,
    externalUserId: user.externalUserId ?? '',
    username: user.username,
    displayName: user.displayName ?? '',
    email: user.email ?? '',
    phone: user.phone ?? '',
    avatarUrl: user.avatarUrl ?? '',
    password: '',
    gatewayTenantId: user.gatewayTenantId ?? '',
    tenantId: user.tenantId ?? '',
    tenantKey: user.tenantKey ?? '',
    defaultUserGroupId: user.defaultUserGroupId ?? '',
    roles: roleValue(user.roles),
    authProfileJson: stringifyJson(user.authProfile),
    metadataJson: stringifyJson(user.metadata),
    status: user.status,
  };
}

function formToUserPayload(form: UserForm): GatewayUserUpsertRequest {
  return {
    userKey: form.userKey.trim() || undefined,
    source: form.source,
    externalUserId: form.externalUserId.trim() || undefined,
    username: form.username.trim(),
    displayName: form.displayName.trim() || undefined,
    email: form.email.trim() || undefined,
    phone: form.phone.trim() || undefined,
    avatarUrl: form.avatarUrl.trim() || undefined,
    password: form.password || undefined,
    gatewayTenantId: form.gatewayTenantId || undefined,
    tenantId: form.tenantId.trim() || undefined,
    tenantKey: form.tenantKey.trim() || undefined,
    defaultUserGroupId: form.defaultUserGroupId || undefined,
    roles: [roleValue([form.roles])],
    authProfile: parseJsonObject(form.authProfileJson, '授权资料 JSON'),
    metadata: parseJsonObject(form.metadataJson, '元数据 JSON'),
    status: form.status,
  };
}

function defaultUserGroupForm(): UserGroupForm {
  return {
    groupKey: `group-${Date.now().toString(36)}`,
    name: '默认用户组',
    description: '',
    source: 'gateway',
    priority: '100',
    rechargeDiscountFactor: '1',
    rechargeDiscountPolicy: {},
    billingDiscountFactor: '1',
    billingDiscountPolicy: {},
    rateLimitPolicyJson: '{"rules":[]}',
    quotaPolicyJson: '{}',
    metadataJson: '{}',
    status: 'active',
  };
}

function userGroupToForm(group: UserGroup): UserGroupForm {
  return {
    groupKey: group.groupKey,
    name: group.name,
    description: group.description ?? '',
    source: group.source,
    priority: String(group.priority),
    rechargeDiscountFactor: discountFactorText(group.rechargeDiscountPolicy),
    rechargeDiscountPolicy: group.rechargeDiscountPolicy ?? {},
    billingDiscountFactor: discountFactorText(group.billingDiscountPolicy),
    billingDiscountPolicy: group.billingDiscountPolicy ?? {},
    rateLimitPolicyJson: stringifyJson(group.rateLimitPolicy),
    quotaPolicyJson: stringifyJson(group.quotaPolicy),
    metadataJson: stringifyJson(group.metadata),
    status: group.status,
  };
}

function formToUserGroupPayload(form: UserGroupForm): UserGroupUpsertRequest {
  return {
    groupKey: form.groupKey.trim(),
    name: form.name.trim(),
    description: form.description.trim() || undefined,
    source: form.source,
    priority: Number(form.priority) || 100,
    rechargeDiscountPolicy: discountPolicyPayload(form.rechargeDiscountPolicy, form.rechargeDiscountFactor, '充值折扣系数'),
    billingDiscountPolicy: discountPolicyPayload(form.billingDiscountPolicy, form.billingDiscountFactor, '计费折扣系数'),
    rateLimitPolicy: parseJsonObject(form.rateLimitPolicyJson, '限流策略 JSON'),
    quotaPolicy: parseJsonObject(form.quotaPolicyJson, '额度策略 JSON'),
    metadata: parseJsonObject(form.metadataJson, '元数据 JSON'),
    status: form.status,
  };
}

function tenantName(tenants: GatewayTenant[], tenantId?: string, fallback?: string) {
  if (!tenantId) return fallback || '未设置';
  return tenants.find((tenant) => tenant.id === tenantId)?.name ?? fallback ?? tenantId;
}

function groupName(groups: UserGroup[], groupId?: string) {
  if (!groupId) return '未设置';
  return groups.find((group) => group.id === groupId)?.name ?? groupId;
}

function roleValue(roles?: string[]) {
  if (roles?.includes('manager')) return 'manager';
  if (roles?.includes('admin')) return 'admin';
  if (roles?.includes('operator')) return 'operator';
  if (roles?.includes('creator')) return 'creator';
  return 'user';
}

function roleLabel(roles?: string[]) {
  return roleOptions.find((role) => role.value === roleValue(roles))?.label ?? '普通用户';
}

function primaryWallet(user: GatewayUser): GatewayWalletAccount | undefined {
  return (user.walletAccounts ?? []).find((account) => account.currency === 'resource') ?? user.walletAccounts?.[0];
}

function walletSummary(user: GatewayUser) {
  const wallet = primaryWallet(user);
  if (!wallet) return '0 resource';
  return `${formatBalance(wallet.balance)} ${wallet.currency}`;
}

function formatBalance(value: number) {
  return new Intl.NumberFormat('zh-CN', { maximumFractionDigits: 6 }).format(value);
}

function newIdempotencyKey() {
  if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {
    return crypto.randomUUID();
  }
  return `wallet-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
}

function discountSummary(group: UserGroup) {
  const billing = discountFactorFromPolicy(group.billingDiscountPolicy);
  const recharge = discountFactorFromPolicy(group.rechargeDiscountPolicy);
  const parts = [];
  if (billing) parts.push(`计费 ${trimNumber(billing)}`);
  if (recharge) parts.push(`充值 ${trimNumber(recharge)}`);
  return parts.join(' / ') || '未设置';
}

function discountFactorText(policy?: Record<string, unknown>) {
  const value = discountFactorFromPolicy(policy);
  return value ? trimNumber(value) : '1';
}

function discountFactorFromPolicy(policy?: Record<string, unknown>) {
  return numberFromUnknown(policy?.discountFactor) ?? numberFromUnknown(policy?.factor);
}

function discountPolicyPayload(basePolicy: Record<string, unknown>, discountText: string, label: string) {
  const policy = { ...basePolicy };
  delete policy.discountFactor;
  delete policy.factor;
  const discount = optionalPositiveNumber(discountText, label);
  if (discount && discount !== 1) {
    policy.discountFactor = discount;
  }
  return Object.keys(policy).length ? policy : undefined;
}

function optionalPositiveNumber(value: string, label: string) {
  const text = value.trim();
  if (!text) return undefined;
  const parsed = Number(text);
  if (!Number.isFinite(parsed) || parsed <= 0) {
    throw new Error(`${label} 必须是大于 0 的数字`);
  }
  return parsed;
}

function numberFromUnknown(value: unknown) {
  if (typeof value === 'number' && Number.isFinite(value) && value > 0) return value;
  if (typeof value === 'string' && value.trim()) {
    const parsed = Number(value);
    if (Number.isFinite(parsed) && parsed > 0) return parsed;
  }
  return undefined;
}

function trimNumber(value: number) {
  return value.toFixed(6).replace(/\.?0+$/, '');
}

function policyKeys(value?: Record<string, unknown>) {
  if (!value) return [];
  return Object.keys(value).slice(0, 3);
}

function stringifyJson(value: unknown) {
  if (!value || (typeof value === 'object' && Object.keys(value as Record<string, unknown>).length === 0)) return '{}';
  return JSON.stringify(value, null, 2);
}

function parseJsonObject(value: string, label: string): Record<string, unknown> | undefined {
  const text = value.trim();
  if (!text || text === '{}') return undefined;
  const parsed = JSON.parse(text) as unknown;
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
    throw new Error(`${label} 必须是 JSON 对象`);
  }
  return parsed as Record<string, unknown>;
}
