import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Button, Divider, Modal, Popover, Tag, Tooltip, message } from 'antd';
import {
  CopyOutlined,
  DownloadOutlined,
  EyeOutlined,
  QrcodeOutlined,
  ReloadOutlined,
} from '@ant-design/icons';

import { ClipboardManager, FileManager, HttpUtil, IntlUtil, SizeFormatter } from '@/utils';
import { formatInboundLabel, formatTunnelConfigMeta } from '@/lib/inbounds/label';
import { normalizeClientIps, type ClientIpInfo } from '@/lib/clients/ip-log';
import { useDatepicker } from '@/hooks/useDatepicker';
import { useClientHwids } from '@/hooks/useClientHwids';
import type { ClientRecord, InboundOption } from '@/hooks/useClients';
import { isPostQuantumLink } from '@/lib/xray/inbound-link';
import { LinkTags, linkMetaText, parseLinkParts } from '@/lib/xray/link-label';
import { QrPanel } from '@/pages/inbounds/qr';
import ClientHwidListModal from '@/components/clients/ClientHwidList';
import ConfigBlock from '@/components/clients/ConfigBlock';
import {
  buildWireguardClientConfig,
  findWireguardInbounds,
  isWireguardClient,
} from './wireguardConfig';
import {
  buildAmneziaWGClientConfig,
  findAmneziaWGInbounds,
  isAmneziaWGClient,
} from './amneziawgConfig';
import './ClientInfoModal.css';

const INBOUND_PROTOCOL_COLORS: Record<string, string> = {
  vless: 'blue',
  vmess: 'geekblue',
  trojan: 'volcano',
  shadowsocks: 'magenta',
  hysteria: 'cyan',
  hysteria2: 'green',
  wireguard: 'gold',
  amneziawg: 'yellow',
  http: 'purple',
  mixed: 'lime',
  tunnel: 'orange',
};

const INBOUND_CHIP_LIMIT = 1;

interface SubSettings {
  enable: boolean;
  subURI: string;
  subJsonURI: string;
  subJsonEnable: boolean;
  subClashURI: string;
  subClashEnable: boolean;
  publicHost?: string;
}

interface ClientInfoModalProps {
  open: boolean;
  client: ClientRecord | null;
  inboundsById: Record<number, InboundOption>;
  tunnelAllowedIPs?: Record<number, string>;
  isOnline: boolean;
  subSettings?: SubSettings;
  onOpenChange: (open: boolean) => void;
}

interface ApiMsg<T = unknown> {
  success?: boolean;
  obj?: T;
}

const DEFAULT_SUB: SubSettings = {
  enable: false,
  subURI: '',
  subJsonURI: '',
  subJsonEnable: false,
  subClashURI: '',
  subClashEnable: false,
  publicHost: '',
};

const SUBSCRIPTION_DOWNLOAD_NAMES = {
  standard: 'subscription-standard.txt',
  json: 'subscription-json.json',
  clash: 'subscription-clash.yaml',
} as const;

export default function ClientInfoModal({
  open,
  client,
  inboundsById,
  tunnelAllowedIPs,
  isOnline,
  subSettings = DEFAULT_SUB,
  onOpenChange,
}: ClientInfoModalProps) {
  const { datepicker } = useDatepicker();
  const { t } = useTranslation();
  const expiryLabel = (ts?: number) => {
    if (!ts) return '∞';
    if (ts < 0) {
      const days = Math.round(ts / -86400000);
      return `${t('pages.clients.delayedStart')}: ${days}d`;
    }
    return IntlUtil.formatDate(ts, datepicker);
  };
  const dateLabel = (ts?: number) => (!ts || ts <= 0 ? '-' : IntlUtil.formatDate(ts, datepicker));
  const [messageApi, messageContextHolder] = message.useMessage();
  const [links, setLinks] = useState<string[]>([]);
  const [clientIps, setClientIps] = useState<ClientIpInfo[]>([]);
  const [ipsLoading, setIpsLoading] = useState(false);
  const [ipsClearing, setIpsClearing] = useState(false);
  const [ipsModalOpen, setIpsModalOpen] = useState(false);
  const {
    clientHwids,
    hwidsLoading,
    hwidsClearing,
    deletingHwidId,
    loadHwids,
    clearHwids,
    deleteHwid,
    resetHwids,
  } = useClientHwids(client?.email);
  const [hwidsModalOpen, setHwidsModalOpen] = useState(false);
  const [downloadingFormat, setDownloadingFormat] = useState<
    keyof typeof SUBSCRIPTION_DOWNLOAD_NAMES | null
  >(null);

  // Clearing on close happens during render; the effect owns only the fetch.
  const openSubId = open ? (client?.subId ?? '') : null;
  const [syncedSubId, setSyncedSubId] = useState(openSubId);
  if (openSubId !== syncedSubId) {
    setSyncedSubId(openSubId);
    if (openSubId === null) {
      setLinks([]);
      setClientIps([]);
      setIpsModalOpen(false);
      resetHwids();
      setHwidsModalOpen(false);
    }
  }

  useEffect(() => {
    if (!open || !client?.subId) return;
    let cancelled = false;
    (async () => {
      const msg = (await HttpUtil.get(
        `/panel/api/clients/subLinks/${encodeURIComponent(client.subId!)}`,
      )) as ApiMsg<string[]>;
      if (cancelled) return;
      setLinks(msg?.success && Array.isArray(msg.obj) ? msg.obj : []);
    })();
    return () => {
      cancelled = true;
    };
  }, [open, client?.subId]);

  const traffic = client?.traffic || null;
  const totalBytes = client?.totalGB || 0;
  const used = (traffic?.up || 0) + (traffic?.down || 0);
  const remaining = useMemo(() => {
    if (totalBytes <= 0) return -1;
    const r = totalBytes - used;
    return r > 0 ? r : 0;
  }, [totalBytes, used]);

  const subId = client?.subId;
  const subLink = subId && subSettings?.subURI ? subSettings.subURI + subId : '';
  const subJsonLink =
    subId && subSettings?.subJsonEnable && subSettings?.subJsonURI
      ? subSettings.subJsonURI + subId
      : '';
  const subClashLink =
    subId && subSettings?.subClashEnable && subSettings?.subClashURI
      ? subSettings.subClashURI + subId
      : '';

  const showSubscription = !!(subSettings?.enable && client?.subId);
  const wgInbounds = useMemo(
    () => findWireguardInbounds(client, inboundsById),
    [client, inboundsById],
  );
  const wgConfigs = useMemo(() => {
    if (!client || !isWireguardClient(client)) return [];
    return wgInbounds
      .map((ib) => {
        const address = tunnelAllowedIPs?.[ib.id] ?? '';
        const text = buildWireguardClientConfig(
          client,
          ib,
          window.location.hostname,
          subSettings?.publicHost ?? '',
          address,
        );
        return { inbound: ib, text };
      })
      .filter((c) => !!c.text);
  }, [client, wgInbounds, tunnelAllowedIPs, subSettings?.publicHost]);

  const awgInbounds = useMemo(
    () => findAmneziaWGInbounds(client, inboundsById),
    [client, inboundsById],
  );
  const awgConfigs = useMemo(() => {
    if (!client || !isAmneziaWGClient(client)) return [];
    return awgInbounds
      .map((ib) => {
        const address = tunnelAllowedIPs?.[ib.id] ?? '';
        const text = buildAmneziaWGClientConfig(
          client,
          ib,
          window.location.hostname,
          subSettings?.publicHost ?? '',
          address,
        );
        return { inbound: ib, text };
      })
      .filter((c) => !!c.text);
  }, [client, awgInbounds, tunnelAllowedIPs, subSettings?.publicHost]);

  async function copyValue(text: string) {
    if (!text) return;
    const ok = await ClipboardManager.copyText(String(text));
    if (ok) messageApi.success(t('copied'));
  }

  async function downloadSubscription(
    url: string,
    format: keyof typeof SUBSCRIPTION_DOWNLOAD_NAMES,
  ) {
    if (!url || downloadingFormat) return;
    setDownloadingFormat(format);
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error('Subscription download failed');
      const content = await response.text();
      FileManager.downloadTextFile(content, SUBSCRIPTION_DOWNLOAD_NAMES[format]);
    } catch (_) {
      messageApi.error(t('somethingWentWrong'));
    } finally {
      setDownloadingFormat(null);
    }
  }

  async function loadIps() {
    if (!client?.email) return;
    setIpsLoading(true);
    try {
      const msg = (await HttpUtil.post(
        `/panel/api/clients/ips/${encodeURIComponent(client.email)}`,
      )) as ApiMsg<unknown[]>;
      if (!msg?.success) {
        setClientIps([]);
        return;
      }
      setClientIps(normalizeClientIps(msg.obj));
    } finally {
      setIpsLoading(false);
    }
  }

  async function clearIps() {
    if (!client?.email) return;
    setIpsClearing(true);
    try {
      const msg = (await HttpUtil.post(
        `/panel/api/clients/clearIps/${encodeURIComponent(client.email)}`,
      )) as ApiMsg;
      if (msg?.success) setClientIps([]);
    } finally {
      setIpsClearing(false);
    }
  }

  function openIpsModal() {
    setIpsModalOpen(true);
    if (clientIps.length === 0) void loadIps();
  }

  function openHwidsModal() {
    setHwidsModalOpen(true);
    if (clientHwids.length === 0) void loadHwids();
  }

  return (
    <>
      {messageContextHolder}
      <Modal
        open={open}
        title={
          client
            ? `${t('pages.clients.clientInfo')} — ${client.email}`
            : t('pages.clients.clientInfo')
        }
        footer={null}
        width={640}
        onCancel={() => onOpenChange(false)}
      >
        {client && (
          <>
            <table className="info-table block">
              <tbody>
                <tr>
                  <td>{t('pages.clients.online')}</td>
                  <td>
                    {client.enable && isOnline ? (
                      <Tag color="green">{t('pages.clients.online')}</Tag>
                    ) : (
                      <Tag>{t('pages.clients.offline')}</Tag>
                    )}
                    <span className="hint">
                      {t('lastOnline')}: {dateLabel(traffic?.lastOnline)}
                      {' · '}
                      {t('lastSubFetch')}: {dateLabel(traffic?.lastSubFetch)}
                    </span>
                  </td>
                </tr>
                <tr>
                  <td>{t('status')}</td>
                  <td>
                    <Tag color={client.enable ? 'green' : 'default'}>
                      {client.enable ? t('enabled') : t('disabled')}
                    </Tag>
                  </td>
                </tr>
                <tr>
                  <td>{t('pages.clients.email')}</td>
                  <td>
                    {client.email ? (
                      <Tag color="green">{client.email}</Tag>
                    ) : (
                      <Tag color="red">{t('none')}</Tag>
                    )}
                  </td>
                </tr>
                <tr>
                  <td>{t('pages.clients.subId')}</td>
                  <td>
                    <Tag className="info-large-tag">{client.subId || '-'}</Tag>
                    {client.subId && (
                      <Button
                        size="small"
                        type="text"
                        icon={<CopyOutlined />}
                        aria-label={t('copy')}
                        onClick={() => copyValue(client.subId!)}
                      />
                    )}
                  </td>
                </tr>
                {client.uuid && (
                  <tr>
                    <td>{t('pages.clients.uuid')}</td>
                    <td>
                      <Tag className="info-large-tag">{client.uuid}</Tag>
                      <Button
                        size="small"
                        type="text"
                        icon={<CopyOutlined />}
                        aria-label={t('copy')}
                        onClick={() => copyValue(client.uuid!)}
                      />
                    </td>
                  </tr>
                )}
                {client.password && (
                  <tr>
                    <td>{t('password')}</td>
                    <td>
                      <Tag className="info-large-tag">{client.password}</Tag>
                      <Button
                        size="small"
                        type="text"
                        icon={<CopyOutlined />}
                        aria-label={t('copy')}
                        onClick={() => copyValue(client.password!)}
                      />
                    </td>
                  </tr>
                )}
                {client.auth && (
                  <tr>
                    <td>{t('pages.clients.auth')}</td>
                    <td>
                      <Tag className="info-large-tag">{client.auth}</Tag>
                      <Button
                        size="small"
                        type="text"
                        icon={<CopyOutlined />}
                        aria-label={t('copy')}
                        onClick={() => copyValue(client.auth!)}
                      />
                    </td>
                  </tr>
                )}
                <tr>
                  <td>{t('pages.clients.flow')}</td>
                  <td>
                    {client.flow ? <Tag>{client.flow}</Tag> : <Tag color="orange">{t('none')}</Tag>}
                  </td>
                </tr>
                <tr>
                  <td>{t('pages.inbounds.traffic')}</td>
                  <td>
                    <Tag>
                      ↑ {SizeFormatter.sizeFormat(traffic?.up || 0)} / ↓{' '}
                      {SizeFormatter.sizeFormat(traffic?.down || 0)}
                    </Tag>
                    <span className="hint">
                      {SizeFormatter.sizeFormat(used)} /{' '}
                      {totalBytes > 0 ? SizeFormatter.sizeFormat(totalBytes) : '∞'}
                    </span>
                  </td>
                </tr>
                <tr>
                  <td>{t('remained')}</td>
                  <td>
                    {remaining < 0 ? (
                      <Tag color="purple">∞</Tag>
                    ) : (
                      <Tag color={remaining > 0 ? '' : 'red'}>
                        {SizeFormatter.sizeFormat(remaining)}
                      </Tag>
                    )}
                  </td>
                </tr>
                <tr>
                  <td>{t('pages.inbounds.expireDate')}</td>
                  <td>
                    {!client.expiryTime ? (
                      <Tag color="purple">∞</Tag>
                    ) : (
                      <Tag color={client.expiryTime < 0 ? 'blue' : undefined}>
                        {expiryLabel(client.expiryTime)}
                      </Tag>
                    )}
                    {(client.expiryTime ?? 0) > 0 && (
                      <span className="hint">{IntlUtil.formatRelativeTime(client.expiryTime)}</span>
                    )}
                  </td>
                </tr>
                <tr>
                  <td>{t('pages.clients.ipLimit')}</td>
                  <td>{!client.limitIp ? <Tag>∞</Tag> : <Tag>{client.limitIp}</Tag>}</td>
                </tr>
                <tr>
                  <td>{t('pages.inbounds.IPLimitlog')}</td>
                  <td>
                    <Button
                      size="small"
                      icon={<EyeOutlined />}
                      aria-label={t('pages.clients.ipLog')}
                      loading={ipsLoading}
                      onClick={openIpsModal}
                    >
                      {clientIps.length > 0 ? clientIps.length : ''}
                    </Button>
                  </td>
                </tr>
                {(traffic?.resetMax ?? 0) > 0 && (
                  <tr>
                    <td>{t('pages.clients.renewsUsed')}</td>
                    <td>
                      <Tag
                        color={
                          (traffic?.resetCount ?? 0) >= (traffic?.resetMax ?? 0) ? 'red' : 'blue'
                        }
                      >
                        {traffic?.resetCount ?? 0} / {traffic?.resetMax}
                      </Tag>
                    </td>
                  </tr>
                )}
                <tr>
                  <td>{t('pages.clients.limitHwid')}</td>
                  <td>{!client.limitHwid ? <Tag>∞</Tag> : <Tag>{client.limitHwid}</Tag>}</td>
                </tr>
                <tr>
                  <td>{t('pages.clients.hwidLog')}</td>
                  <td>
                    <Button
                      size="small"
                      icon={<EyeOutlined />}
                      aria-label={t('pages.clients.hwidLog')}
                      loading={hwidsLoading}
                      onClick={openHwidsModal}
                    >
                      {clientHwids.length > 0 ? clientHwids.length : ''}
                    </Button>
                  </td>
                </tr>
                <tr>
                  <td>{t('pages.inbounds.createdAt')}</td>
                  <td>
                    <Tag>{dateLabel(client.createdAt)}</Tag>
                  </td>
                </tr>
                <tr>
                  <td>{t('pages.inbounds.updatedAt')}</td>
                  <td>
                    <Tag>{dateLabel(client.updatedAt)}</Tag>
                  </td>
                </tr>
                {client.group && (
                  <tr>
                    <td>{t('pages.clients.group')}</td>
                    <td>
                      <Tag color="geekblue">{client.group}</Tag>
                    </td>
                  </tr>
                )}
                {client.comment && (
                  <tr>
                    <td>{t('pages.clients.comment')}</td>
                    <td>
                      <Tag className="info-large-tag">{client.comment}</Tag>
                    </td>
                  </tr>
                )}
                <tr>
                  <td>{t('pages.clients.attachedInbounds')}</td>
                  <td>
                    {(() => {
                      const ids = client.inboundIds || [];
                      if (ids.length === 0) return <span className="hint">—</span>;
                      const visible = ids.slice(0, INBOUND_CHIP_LIMIT);
                      const overflow = ids.slice(INBOUND_CHIP_LIMIT);
                      const inboundChip = (id: number) => {
                        const ib = inboundsById[id];
                        const proto = (ib?.protocol || '').toLowerCase();
                        const color = INBOUND_PROTOCOL_COLORS[proto] ?? 'default';
                        const label = formatInboundLabel(ib?.tag, ib?.remark);
                        return (
                          <Tooltip key={id} title={label}>
                            <Tag color={color}>{label}</Tag>
                          </Tooltip>
                        );
                      };
                      return (
                        <div className="chips">
                          {visible.map((id) => inboundChip(id))}
                          {overflow.length > 0 && (
                            <Popover
                              trigger="click"
                              placement="bottomRight"
                              content={
                                <div className="chips chips-stack">
                                  {overflow.map((id) => inboundChip(id))}
                                </div>
                              }
                            >
                              <Tag color="default" className="chip-more">
                                +{overflow.length} {t('more') !== 'more' ? t('more') : 'more'}
                              </Tag>
                            </Popover>
                          )}
                        </div>
                      );
                    })()}
                  </td>
                </tr>
              </tbody>
            </table>

            {showSubscription && subLink && (
              <>
                <Divider>{t('subscription.title')}</Divider>
                <div className="link-row">
                  <Tag color="green" className="link-row-tag">
                    SUB
                  </Tag>
                  <a
                    href={subLink}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="link-row-title link-row-title-anchor"
                    title={subLink}
                  >
                    {client.subId}
                  </a>
                  <div className="link-row-actions">
                    <Tooltip title={t('copy')}>
                      <Button
                        size="small"
                        icon={<CopyOutlined />}
                        aria-label={t('copy')}
                        onClick={() => copyValue(subLink)}
                      />
                    </Tooltip>
                    <Tooltip title={t('download')}>
                      <Button
                        size="small"
                        icon={<DownloadOutlined />}
                        aria-label={t('download')}
                        loading={downloadingFormat === 'standard'}
                        disabled={downloadingFormat !== null}
                        onClick={() => void downloadSubscription(subLink, 'standard')}
                      />
                    </Tooltip>
                    <Popover
                      trigger="click"
                      placement="left"
                      destroyOnHidden
                      content={
                        <QrPanel
                          value={subLink}
                          remark={`${client.email} — ${t('subscription.title')}`}
                          size={220}
                        />
                      }
                    >
                      <Tooltip title={t('pages.clients.qrCode')}>
                        <Button
                          size="small"
                          icon={<QrcodeOutlined />}
                          aria-label={t('pages.clients.qrCode')}
                        />
                      </Tooltip>
                    </Popover>
                  </div>
                </div>
                {subJsonLink && (
                  <div className="link-row">
                    <Tag color="purple" className="link-row-tag">
                      JSON
                    </Tag>
                    <a
                      href={subJsonLink}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="link-row-title link-row-title-anchor"
                      title={subJsonLink}
                    >
                      {client.subId}
                    </a>
                    <div className="link-row-actions">
                      <Tooltip title={t('copy')}>
                        <Button
                          size="small"
                          icon={<CopyOutlined />}
                          aria-label={t('copy')}
                          onClick={() => copyValue(subJsonLink)}
                        />
                      </Tooltip>
                      <Tooltip title={t('download')}>
                        <Button
                          size="small"
                          icon={<DownloadOutlined />}
                          aria-label={t('download')}
                          loading={downloadingFormat === 'json'}
                          disabled={downloadingFormat !== null}
                          onClick={() => void downloadSubscription(subJsonLink, 'json')}
                        />
                      </Tooltip>
                      <Popover
                        trigger="click"
                        placement="left"
                        destroyOnHidden
                        content={
                          <QrPanel
                            value={subJsonLink}
                            remark={`${client.email} — JSON`}
                            size={220}
                          />
                        }
                      >
                        <Tooltip title={t('pages.clients.qrCode')}>
                          <Button
                            size="small"
                            icon={<QrcodeOutlined />}
                            aria-label={t('pages.clients.qrCode')}
                          />
                        </Tooltip>
                      </Popover>
                    </div>
                  </div>
                )}
                {subClashLink && (
                  <div className="link-row">
                    <Tooltip title="Clash / Mihomo">
                      <Tag color="gold" className="link-row-tag">
                        CLASH
                      </Tag>
                    </Tooltip>
                    <a
                      href={subClashLink}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="link-row-title link-row-title-anchor"
                      title={subClashLink}
                    >
                      {client.subId}
                    </a>
                    <div className="link-row-actions">
                      <Tooltip title={t('copy')}>
                        <Button
                          size="small"
                          icon={<CopyOutlined />}
                          aria-label={t('copy')}
                          onClick={() => copyValue(subClashLink)}
                        />
                      </Tooltip>
                      <Tooltip title={t('download')}>
                        <Button
                          size="small"
                          icon={<DownloadOutlined />}
                          aria-label={t('download')}
                          loading={downloadingFormat === 'clash'}
                          disabled={downloadingFormat !== null}
                          onClick={() => void downloadSubscription(subClashLink, 'clash')}
                        />
                      </Tooltip>
                      <Popover
                        trigger="click"
                        placement="left"
                        destroyOnHidden
                        content={
                          <QrPanel
                            value={subClashLink}
                            remark={`${client.email} — Clash / Mihomo`}
                            size={220}
                          />
                        }
                      >
                        <Tooltip title={t('pages.clients.qrCode')}>
                          <Button
                            size="small"
                            icon={<QrcodeOutlined />}
                            aria-label={t('pages.clients.qrCode')}
                          />
                        </Tooltip>
                      </Popover>
                    </div>
                  </div>
                )}
              </>
            )}

            {links.length > 0 && (
              <>
                <Divider>{t('pages.inbounds.copyLink')}</Divider>
                {links.map((link, idx) => {
                  const parts = parseLinkParts(link);
                  const fallback = `${t('pages.clients.link')} ${idx + 1}`;
                  const rowTitle = (parts && linkMetaText(parts)) || fallback;
                  const qrRemark = parts?.remark || rowTitle;
                  const canQr = !isPostQuantumLink(link);
                  return (
                    <div key={idx} className="link-row">
                      {parts ? (
                        <LinkTags parts={parts} />
                      ) : (
                        <Tag className="link-row-tag">LINK</Tag>
                      )}
                      <span className="link-row-title" title={rowTitle}>
                        {rowTitle}
                      </span>
                      <div className="link-row-actions">
                        <Tooltip title={t('copy')}>
                          <Button
                            size="small"
                            icon={<CopyOutlined />}
                            aria-label={t('copy')}
                            onClick={() => copyValue(link)}
                          />
                        </Tooltip>
                        {canQr && (
                          <Popover
                            trigger="click"
                            placement="left"
                            destroyOnHidden
                            content={<QrPanel value={link} remark={qrRemark} size={220} />}
                          >
                            <Tooltip title={t('pages.clients.qrCode')}>
                              <Button
                                size="small"
                                icon={<QrcodeOutlined />}
                                aria-label={t('pages.clients.qrCode')}
                              />
                            </Tooltip>
                          </Popover>
                        )}
                      </div>
                    </div>
                  );
                })}
              </>
            )}

            {wgConfigs.length > 0 && client && (
              <>
                <Divider>{t('pages.clients.wireguardConfig')}</Divider>
                {wgConfigs.map(({ inbound, text }) => {
                  const meta = formatTunnelConfigMeta(inbound, client.email, wgConfigs.length);
                  return (
                    <ConfigBlock
                      key={`wg-${inbound.id}`}
                      label={meta.label || t('pages.clients.config')}
                      text={text}
                      fileName={meta.fileName}
                      qrRemark={meta.qrRemark}
                      tagColor="cyan"
                    />
                  );
                })}
              </>
            )}

            {awgConfigs.length > 0 && client && (
              <>
                <Divider>{t('pages.clients.amneziaWgConfig')}</Divider>
                {awgConfigs.map(({ inbound, text }) => {
                  const meta = formatTunnelConfigMeta(inbound, client.email, awgConfigs.length);
                  return (
                    <ConfigBlock
                      key={`awg-${inbound.id}`}
                      label={meta.label || t('pages.clients.config')}
                      text={text}
                      fileName={meta.fileName}
                      qrRemark={meta.qrRemark}
                      tagColor="purple"
                    />
                  );
                })}
              </>
            )}
          </>
        )}
      </Modal>

      <Modal
        open={ipsModalOpen}
        title={`${t('pages.inbounds.IPLimitlog')}${client?.email ? ` — ${client.email}` : ''}`}
        width={440}
        onCancel={() => setIpsModalOpen(false)}
        footer={[
          <Button key="refresh" icon={<ReloadOutlined />} loading={ipsLoading} onClick={loadIps}>
            {t('refresh')}
          </Button>,
          <Button
            key="clear"
            danger
            loading={ipsClearing}
            disabled={clientIps.length === 0}
            onClick={clearIps}
          >
            {t('pages.clients.clearAll')}
          </Button>,
          <Button key="close" type="primary" onClick={() => setIpsModalOpen(false)}>
            {t('close')}
          </Button>,
        ]}
      >
        {clientIps.length > 0 ? (
          <div style={{ maxHeight: 360, overflowY: 'auto' }}>
            {clientIps.map((entry, idx) => (
              <Tag
                key={idx}
                color="blue"
                style={{
                  display: 'block',
                  width: 'fit-content',
                  maxWidth: '100%',
                  marginBottom: 6,
                  padding: '2px 8px',
                  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
                }}
              >
                {entry.ip}
                {entry.time ? ` (${entry.time})` : ''}
                {entry.node ? (
                  <span style={{ marginInlineStart: 6, opacity: 0.85, fontWeight: 600 }}>
                    @ {entry.node}
                  </span>
                ) : null}
              </Tag>
            ))}
          </div>
        ) : (
          <Tag>{t('tgbot.noIpRecord')}</Tag>
        )}
      </Modal>

      <ClientHwidListModal
        open={hwidsModalOpen}
        email={client?.email}
        hwids={clientHwids}
        loading={hwidsLoading}
        clearing={hwidsClearing}
        deletingId={deletingHwidId}
        formatDate={dateLabel}
        onRefresh={loadHwids}
        onClearAll={clearHwids}
        onDelete={deleteHwid}
        onClose={() => setHwidsModalOpen(false)}
      />
    </>
  );
}
