/**
 * The CRM masks phone / email / name when the agent lacks access:
 * new CRM → "••••••••" / "••••@••••", old CRM → "abc*****" (hide_str).
 * A masked value must never be dialed, emailed or prefilled in a form.
 *
 * Legacy servers may also serialize phones as objects (libphonenumber),
 * so every value coming from the API is normalized to string | null first.
 */

import { detectDefaultCountryCode, parsePhoneToParts } from './phone';

/** Normalize any API value (string, number, object…) to a usable string or null. */
export function contactString(value: unknown): string | null {
  if (value == null) return null;
  if (typeof value === 'string') {
    const v = value.trim();
    return v || null;
  }
  if (typeof value === 'number') return String(value);
  if (typeof value === 'object') {
    const o = value as Record<string, unknown>;
    // JMS-serialized libphonenumber\PhoneNumber: { countryCode, nationalNumber, rawInput }
    if (o.nationalNumber != null) {
      const cc = o.countryCode != null ? String(o.countryCode) : '';
      return `+${cc}${String(o.nationalNumber)}`.replace(/^\+$/, '') || null;
    }
    for (const key of ['e164', 'rawInput', 'number', 'phone', 'value']) {
      const inner = o[key];
      if (typeof inner === 'string' && inner.trim()) return inner.trim();
      if (typeof inner === 'number') return String(inner);
    }
  }
  return null;
}

export function isMaskedContactValue(value?: unknown): boolean {
  const v = contactString(value);
  if (!v) return false;
  return /[*•]/.test(v);
}

/** Returns the value only if it is real and usable, otherwise null. */
export function usableContactValue(value?: unknown): string | null {
  const v = contactString(value);
  if (!v || /[*•]/.test(v)) return null;
  return v;
}

/**
 * Picker hint: country code + first national digit + stars + last 3 digits.
 * Example: +21622123357 → +2162****357
 */
export function maskPhoneHint(value?: unknown): string | null {
  const raw = contactString(value);
  if (!raw) return null;
  if (isMaskedContactValue(raw)) {
    // Already partially hidden by CRM — keep a compact readable form.
    const digitsAndStars = raw.replace(/[^\d*•]/g, '').replace(/•/g, '*');
    return digitsAndStars ? `+${digitsAndStars.replace(/^\+/, '')}` : raw;
  }

  const { prefix, number } = parsePhoneToParts(raw, detectDefaultCountryCode());
  const cc = (prefix || detectDefaultCountryCode()).replace(/\D/g, '');
  let local = (number || '').replace(/\D/g, '');
  if (!local) {
    const all = raw.replace(/\D/g, '');
    if (cc && all.startsWith(cc)) local = all.slice(cc.length);
    else local = all;
  }
  local = local.replace(/^0+/, '');
  if (!local) return cc ? `+${cc}` : null;
  if (local.length <= 4) return `+${cc}${local}`;

  const first = local[0];
  const last3 = local.slice(-3);
  const middleLen = Math.max(4, local.length - 4);
  return `+${cc}${first}${'*'.repeat(middleLen)}${last3}`;
}
