import { isSSMultiUser } from '@/lib/xray/protocol-capabilities';
import { coerceInboundJsonField } from '@/models/dbinbound';

import type { DBInboundRecord, StreamHints } from './types';

export function readStreamHints(streamSettings: unknown): StreamHints {
  const stream = coerceInboundJsonField(streamSettings) as { network?: string; security?: string };
  return {
    network: stream.network ?? '',
    isTls: stream.security === 'tls',
    isReality: stream.security === 'reality',
  };
}

// Display label for a network value. All known transports render in
// upper-case for visual consistency with the TCP/UDP/TLS/Reality tags
// already shown alongside; compound names (`httpupgrade`, `splithttp`,
// `xhttp`) get a tiny touch of casing so they don't read as one word.
export function networkLabel(network: string): string {
  const n = (network || '').toLowerCase();
  if (!n) return 'TCP';
  switch (n) {
    case 'httpupgrade': return 'HTTPUpgrade';
    case 'splithttp': return 'SplitHTTP';
    case 'xhttp': return 'XHTTP';
  }
  return n.toUpperCase();
}

// Returns the underlying L4 protocol for transports whose name isn't
// already TCP/UDP. `kcp` and `quic` both ride on UDP; everything else
// (`ws`, `grpc`, `http`, `httpupgrade`, `xhttp`) is TCP-based and gets
// no extra tag (the transport name implies TCP).
export function networkL4(network: string): 'UDP' | '' {
  const n = (network || '').toLowerCase();
  if (n === 'kcp' || n === 'quic') return 'UDP';
  return '';
}

// Shadowsocks settings.network ("tcp" / "udp" / "tcp,udp") and Tunnel
// settings.allowedNetwork (same shape, different field name) both carry
// the L4 transport list independent of streamSettings. Returns a
// comma-separated label.
export function commaNetworkLabel(raw: string): string {
  const parts = (raw || 'tcp').toLowerCase().split(',').map((p) => p.trim()).filter(Boolean);
  if (parts.length === 0) return 'TCP';
  return parts.map(networkLabel).join(',');
}

export function shadowsocksNetworkLabel(settings: unknown): string {
  return commaNetworkLabel(readSettings(settings).network || '');
}

export function tunnelNetworkLabel(settings: unknown): string {
  return commaNetworkLabel(readSettings(settings).allowedNetwork || '');
}

// Mixed (socks+http combo) is always TCP at L4; settings.udp=true adds
// UDP-associate support on the same port (SOCKS5 UDP).
export function mixedNetworkLabel(settings: unknown): string {
  const st = coerceInboundJsonField(settings) as { udp?: boolean };
  return st.udp ? 'TCP,UDP' : 'TCP';
}

export function readSettings(settings: unknown): { method?: string; network?: string; allowedNetwork?: string } {
  return coerceInboundJsonField(settings) as { method?: string; network?: string; allowedNetwork?: string };
}

export function isInboundMultiUser(record: { protocol: string; settings: unknown }): boolean {
  switch (record.protocol) {
    case 'vmess':
    case 'vless':
    case 'trojan':
    case 'hysteria':
      return true;
    case 'shadowsocks':
      return isSSMultiUser({ protocol: 'shadowsocks', settings: readSettings(record.settings) });
    default:
      return false;
  }
}

export function showQrCodeMenu(dbInbound: DBInboundRecord): boolean {
  if (dbInbound.isWireguard) return true;
  if (dbInbound.isSS) {
    return !isSSMultiUser({ protocol: 'shadowsocks', settings: readSettings(dbInbound.settings) });
  }
  return false;
}
