/**
 * Tests mirror how domainProperties is used in the Communication / Campaigns flow:
 * one API response drives SMS, Email, WhatsApp (WABA), RCS, Viber, Zalo, and LINE
 * sender UI, summary lines, save payload, and gateway validation.
 */
import {
  SMS,
  EMAIL,
  WHATSAPP,
  VIBER,
  RCS,
  ZALO,
  LINE,
} from '../../../../CreativesContainer/constants';
import {
  getSmsDefaultsForDomainId,
  getEmailDefaultsForDomainId,
  getDefaultValueForField,
  getWhatsappAccountName,
  getRcsAccountName,
  FIELD_TYPE,
  DELIVERY_SETTINGS_FIELDS,
  getFieldsForChannels,
  parseEntityForDisplay,
  buildChannelSettingFromFieldValues,
  hasDomainGateway,
  parseChannelSettingForDisplay,
} from '../deliverySettingsConfig';

/** Typical campaigns `domainProperties` entity: channel keys → list of gateway rows */
const domainPropertiesFromApi = {
  SMS: [
    {
      domainProperties: {
        id: 's1',
        domainName: 'Primary SMS gateway',
        contactInfo: [
          {
            type: 'gsm_sender_id', value: '+1001', valid: true, default: true,
          },
          {
            type: 'cdma_sender_id', value: '+cdma-fallback', valid: true, default: false,
          },
        ],
      },
    },
    {
      domainProperties: {
        id: 's2',
        domainName: 'Secondary SMS gateway',
        contactInfo: [{
          type: 'gsm_sender_id', value: '+2002', valid: true, default: true,
        }],
      },
    },
  ],
  EMAIL: [
    {
      domainProperties: {
        id: 'e1',
        domainName: 'Transactional mail',
        contactInfo: [
          {
            type: 'sender_id',
            value: 'noreply@brand.com',
            label: 'Brand',
            valid: true,
            default: true,
          },
          {
            type: 'reply_to_id', value: 'support@brand.com', valid: true, default: true,
          },
        ],
      },
    },
    {
      domainProperties: {
        id: 'e2',
        domainName: 'Promotional mail',
        contactInfo: [
          {
            type: 'sender_id',
            value: 'promo@brand.com',
            label: 'Promo desk',
            valid: true,
            default: true,
          },
        ],
      },
    },
  ],
  WHATSAPP: {
    domainProperties: {
      id: 'wa-1',
      domainName: 'Brand WA',
      connectionProperties: { wabaId: 'waba-99' },
      contactInfo: [{
        type: 'gsm_sender_id', value: '+wa1', valid: true, default: true,
      }],
    },
  },
  RCS: [
    {
      domainProperties: {
        domainName: 'RCS brand',
        contactInfo: [{
          type: 'gsm_sender_id', value: '+rcs1', valid: true, default: true,
        }],
      },
    },
  ],
  VIBER: [
    {
      id: 'vgw-1',
      domainProperties: {
        id: 0,
        domainName: 'Viber gateway',
        contactInfo: [
          {
            type: 'viber_sender_id', value: 'viber-sender-1', valid: true, default: true,
          },
        ],
      },
    },
  ],
  ZALO: [
    {
      domainProperties: {
        id: 'z1',
        domainName: 'Zalo OA 1',
        contactInfo: [{
          type: 'gsm_sender_id', value: '+z1', valid: true, default: true,
        }],
      },
    },
    {
      domainProperties: {
        id: 'z2',
        domainName: 'Zalo OA 2',
        contactInfo: [{
          type: 'gsm_sender_id', value: '+z2', valid: true, default: true,
        }],
      },
    },
  ],
  LINE: [
    {
      domainProperties: {
        id: 'l1',
        domainName: 'LINE channel',
        contactInfo: [{
          type: 'gsm_sender_id', value: '+line1', valid: true, default: true,
        }],
      },
    },
  ],
};

describe('deliverySettingsConfig — user-facing flows', () => {
  describe('SMS: choosing gateway and sender', () => {
    it('defaults to the first gateway’s primary sender, with GSM preferred over CDMA when both exist', () => {
      const entity = domainPropertiesFromApi;
      expect(parseEntityForDisplay(entity).smsSenderId).toBe('+1001');
      expect(getSmsDefaultsForDomainId(entity, 's2').senderId).toBe('+2002');
    });

    it('when only CDMA senders exist for a gateway, still resolves a sender', () => {
      const cdmaOnly = {
        SMS: [
          {
            domainProperties: {
              id: 'c1',
              domainName: 'CDMA-only GW',
              contactInfo: [
                {
                  type: 'cdma_sender_id', value: '+cdma-only', valid: true, default: true,
                },
              ],
            },
          },
        ],
      };
      expect(parseEntityForDisplay(cdmaOnly).smsSenderId).toBe('+cdma-only');
    });

    it('Reset / default helpers respect the gateway the user selected in the form', () => {
      const entity = domainPropertiesFromApi;
      expect(getDefaultValueForField('smsDomain', entity)).toBe('s1');
      expect(
        getDefaultValueForField('smsSenderId', entity, { fieldValues: { smsDomain: 's2' } }),
      ).toBe('+2002');
    });

    it('returns safe empty defaults when domain properties were not loaded', () => {
      expect(getSmsDefaultsForDomainId(null, 's1')).toEqual({ senderId: '' });
    });
  });

  describe('Email: multiple domains, from-address, reply-to', () => {
    const entity = domainPropertiesFromApi;

    it('summary shows the active domain name and default sender for the first gateway', () => {
      const summary = parseEntityForDisplay(entity);
      expect(summary.emailDomain).toBe('Transactional mail');
      expect(summary.emailSenderId).toBe('noreply@brand.com');
    });

    it('when the user switches domain in the form, defaults follow that gateway’s contactInfo', () => {
      const ctx = { fieldValues: { emailDomain: 'e2' } };
      expect(getDefaultValueForField('emailSenderId', entity, ctx)).toBe('promo@brand.com');
      expect(getDefaultValueForField('emailSenderName', entity, ctx)).toBe('Promo desk');
      expect(getEmailDefaultsForDomainId(entity, 'e2').senderId).toBe('promo@brand.com');
    });

    it('some tenants return domain display name on the root object — summary still shows it', () => {
      const legacyShape = {
        EMAIL: [
          {
            id: 'er1',
            domainName: 'Marketing (legacy shape)',
            domainProperties: { id: 'er1', contactInfo: [] },
          },
        ],
      };
      expect(parseEntityForDisplay(legacyShape).emailDomain).toBe('Marketing (legacy shape)');
    });

    it('when multiple sender_id / reply_to rows exist, defaults prefer rows marked default', () => {
      const richDomain = {
        EMAIL: [
          {
            domainProperties: {
              id: 'edef',
              domainName: 'Rich domain',
              contactInfo: [
                {
                  type: 'sender_id',
                  value: 'a@d.com',
                  label: 'Label A',
                  valid: true,
                  default: false,
                },
                {
                  type: 'sender_id',
                  value: 'b@d.com',
                  label: 'Label B',
                  valid: true,
                  default: true,
                },
                {
                  type: 'reply_to_id',
                  value: 'r1@d.com',
                  valid: true,
                  default: false,
                },
                {
                  type: 'reply_to_id',
                  value: 'r2@d.com',
                  valid: true,
                  default: true,
                },
              ],
            },
          },
        ],
      };
      expect(parseEntityForDisplay(richDomain).emailSenderId).toBe('b@d.com');
      expect(getEmailDefaultsForDomainId(richDomain, 'edef').replyToId).toBe('r2@d.com');
      const emailSenderNameField = getFieldsForChannels(['EMAIL']).find(
        (f) => f.fieldKey === 'emailSenderName',
      );
      expect(emailSenderNameField.getValue(richDomain)).toBe('Label B');
    });

    it('returns safe empty defaults when domain properties were not loaded', () => {
      expect(getEmailDefaultsForDomainId(null, 'e1')).toEqual({
        senderId: '',
        senderName: '',
        replyToId: '',
      });
    });
  });

  describe('WhatsApp: template WABA vs connected domains', () => {
    const singleWa = domainPropertiesFromApi;

    it('matches the business account name using the template’s WABA / connection id', () => {
      expect(getWhatsappAccountName(singleWa, 'waba-99')).toBe('Brand WA');
      expect(
        parseEntityForDisplay(singleWa, { whatsappSourceAccountId: 'waba-99' }).whatsappSenderNumber,
      ).toBe('+wa1');
    });

    it('with no WABA on the template, uses the first WhatsApp gateway (single-account setups)', () => {
      expect(getWhatsappAccountName(singleWa, '')).toBe('Brand WA');
    });

    it('if the template WABA does not match any row, UI still binds to the first connected domain', () => {
      const onlyOther = {
        WHATSAPP: [
          {
            domainProperties: {
              domainName: 'Fallback WA',
              connectionProperties: { sourceAccountIdentifier: 'other-waba' },
              contactInfo: [{
                type: 'gsm_sender_id', value: '+x', valid: true, default: true,
              }],
            },
          },
        ],
      };
      expect(getWhatsappAccountName(onlyOther, 'unknown-waba')).toBe('Fallback WA');
    });

    it('no entity → no account label (e.g. fetch failed)', () => {
      expect(getWhatsappAccountName(null, 'waba-99')).toBe('');
    });
  });

  describe('RCS: brand line in summary', () => {
    it('shows RCS brand and number; combined creative prefers WhatsApp for the shared senderNumber slot', () => {
      const entity = domainPropertiesFromApi;
      expect(getRcsAccountName(entity)).toBe('RCS brand');
      const summary = parseEntityForDisplay(entity);
      expect(summary.rcsSenderNumber).toBe('+rcs1');
      expect(summary.senderNumber).toBe('+wa1');
    });

    it('RCS-only creative uses RCS for the shared senderNumber line', () => {
      const rcsOnly = { RCS: domainPropertiesFromApi.RCS };
      expect(parseEntityForDisplay(rcsOnly).senderNumber).toBe('+rcs1');
    });

    it('empty payload → no RCS label', () => {
      expect(getRcsAccountName({})).toBe('');
    });
  });

  describe('Viber: gateway id 0 + alternate API sender types', () => {
    it('uses viber_sender_id when GSM is not present (API variance)', () => {
      const entity = domainPropertiesFromApi;
      expect(parseEntityForDisplay(entity).viberSenderId).toBe('viber-sender-1');
    });

    it('Iris-style mapping: domainProperties.id is 0, real gateway id on parent — account select still works', () => {
      const entity = {
        VIBER: [
          {
            domainProperties: {
              id: 0,
              domainName: 'Primary',
              contactInfo: [],
            },
            id: 'gateway-x',
          },
          {
            domainProperties: {
              id: 5,
              domainName: 'Listed',
              contactInfo: [],
            },
          },
        ],
      };
      const viberAccountField = getFieldsForChannels(['VIBER']).find(
        (f) => f.fieldKey === 'viberAccount',
      );
      const opts = viberAccountField.getOptions(entity);
      expect(opts.map((o) => o.value)).toEqual(expect.arrayContaining(['gateway-x', 5]));
    });
  });

  describe('Zalo / LINE: multiple official accounts', () => {
    it('aggregates sender options across all returned gateways for the channel', () => {
      const zaloField = getFieldsForChannels(['ZALO'])[0];
      const opts = zaloField.getOptions(domainPropertiesFromApi);
      const values = opts.map((o) => o.value);
      expect(values).toEqual(expect.arrayContaining(['+z1', '+z2']));
    });
  });

  describe('Which delivery fields appear (channel enablement)', () => {
    it('only includes field configs for channels in the creative / flow', () => {
      expect(FIELD_TYPE.SELECT).toBe('select');
      expect(DELIVERY_SETTINGS_FIELDS.length).toBeGreaterThan(5);
      const keys = getFieldsForChannels(['sms', 'EMAIL', '', null]).map((f) => f.fieldKey);
      expect(keys).toEqual(
        expect.arrayContaining(['smsDomain', 'smsSenderId', 'emailDomain', 'emailSenderId']),
      );
    });

    it('for a full multi-channel response, every configured getter runs without throwing', () => {
      const combined = domainPropertiesFromApi;
      const waCtx = { whatsappSourceAccountId: 'waba-99' };
      const fields = getFieldsForChannels([
        'SMS',
        'EMAIL',
        'WHATSAPP',
        'RCS',
        'VIBER',
        'ZALO',
        'LINE',
      ]);
      fields.forEach((f) => {
        const ctx = f.fieldKey === 'whatsappSenderNumber' ? { fieldValues: {}, ...waCtx } : { fieldValues: {} };
        if (typeof f.getValue === 'function') f.getValue(combined, ctx);
        if (typeof f.getOptions === 'function') f.getOptions(combined, ctx);
      });
    });

    it('SMS label-only contact row still yields a display value', () => {
      const labelOnlySms = {
        SMS: [
          {
            domainProperties: {
              id: 'lbl',
              domainName: 'Lbl GW',
              contactInfo: [
                {
                  type: 'gsm_sender_id', label: 'only-label', valid: true, default: true,
                },
              ],
            },
          },
        ],
      };
      getFieldsForChannels(['SMS']).forEach((f) => {
        f.getValue(labelOnlySms, { fieldValues: {} });
        f.getOptions(labelOnlySms);
      });
      expect(parseEntityForDisplay(labelOnlySms).smsSenderId).toBe('only-label');
    });
  });

  describe('Save + reopen', () => {
    it('buildChannelSettingFromFieldValues matches what campaigns expect on save', () => {
      const saved = buildChannelSettingFromFieldValues({
        smsDomain: 'd1',
        smsSenderId: 'g1',
        emailDomain: 'ed',
        emailSenderId: 'mail@x.com',
        emailSenderName: 'N',
        emailReplyToId: 'r@x.com',
        whatsappSenderNumber: '+w',
        whatsappDomainId: 'wd',
        whatsappAccount: 'acc',
        rcsSenderNumber: '+r',
        rcsAccount: 'rcs-acc',
        viberAccount: 'va',
        viberSenderId: 'vs',
        zaloSenderId: 'zs',
        lineSenderId: 'ls',
      });
      expect(saved).toEqual({
        SMS: { domainId: 'd1', gsmSenderId: 'g1' },
        EMAIL: {
          domainId: 'ed',
          senderEmail: 'mail@x.com',
          senderLabel: 'N',
          senderReplyTo: 'r@x.com',
        },
        WHATSAPP: { domainId: 'wd', senderMobNum: '+w' },
        RCS: { senderMobNum: '+r', rcsSender: '+r' },
        VIBER: { domainId: 'va', sender: 'vs', gsmSenderId: 'vs' },
        ZALO: { zaloSenderId: 'zs' },
        LINE: { lineSenderId: 'ls' },
      });
    });

    it('parseChannelSettingForDisplay hydrates form-shaped values when editing an existing creative', () => {
      const flat = parseChannelSettingForDisplay({
        SMS: { domainId: 'd', gsmSenderId: 'g' },
        EMAIL: {
          domainId: 'ed',
          senderEmail: 'e@e.com',
          senderLabel: 'L',
          senderReplyTo: 'r@e.com',
        },
        WHATSAPP: { senderMobNum: '+w', domainId: 'wid' },
        RCS: { rcsSender: '+r' },
        VIBER: { domainId: 'vd', viberSenderId: 'vx' },
        ZALO: { zaloSenderId: 'zz' },
        LINE: { lineSenderId: 'll' },
      });
      expect(flat).toMatchObject({
        smsDomain: 'd',
        smsSenderId: 'g',
        emailDomain: 'ed',
        whatsappDomainId: 'wid',
        viberSenderId: 'vx',
      });
      expect(parseChannelSettingForDisplay({ VIBER: { domainId: 'd', gsmSenderId: 'gsm' } }).viberSenderId).toBe(
        'gsm',
      );
      expect(parseChannelSettingForDisplay({ VIBER: { domainId: 'd', sender: 's' } }).viberSenderId).toBe('s');
    });

    it('nothing saved yet → empty channelSetting object', () => {
      expect(buildChannelSettingFromFieldValues({})).toEqual({});
      expect(parseChannelSettingForDisplay()).toEqual({});
    });
  });

  describe('Gateway checks before showing delivery errors', () => {
    it('SMS / Email / WhatsApp / Viber / RCS need a non-empty gateway list when we validate', () => {
      expect(hasDomainGateway(null, SMS)).toBe(false);
      expect(hasDomainGateway({ SMS: [] }, SMS)).toBe(false);
      expect(hasDomainGateway(domainPropertiesFromApi, SMS)).toBe(true);
      expect(hasDomainGateway(domainPropertiesFromApi, EMAIL)).toBe(true);
      expect(hasDomainGateway(domainPropertiesFromApi, VIBER)).toBe(true);
      expect(hasDomainGateway(domainPropertiesFromApi, RCS)).toBe(true);
    });

    it('WhatsApp also requires at least one sendable number on the matched (or fallback) domain', () => {
      expect(hasDomainGateway({ WHATSAPP: [] }, WHATSAPP)).toBe(false);
      expect(
        hasDomainGateway(domainPropertiesFromApi, WHATSAPP, { whatsappSourceAccountId: 'waba-99' }),
      ).toBe(true);
      const noSenders = {
        WHATSAPP: [
          {
            domainProperties: {
              connectionProperties: { sourceAccountIdentifier: 'x' },
              contactInfo: [],
            },
          },
        ],
      };
      expect(hasDomainGateway(noSenders, WHATSAPP, { whatsappSourceAccountId: 'x' })).toBe(false);
    });

    it('Zalo and Line are not blocked by the domain-gateway gate (product rules)', () => {
      expect(hasDomainGateway({}, ZALO)).toBe(true);
      expect(hasDomainGateway({}, LINE)).toBe(true);
    });
  });

  describe('parseEntityForDisplay', () => {
    it('returns null when the parent has not loaded entity yet', () => {
      expect(parseEntityForDisplay(null)).toBeNull();
    });
  });

  describe('getDefaultValueForField — edge cases', () => {
    it('unknown field keys do not break reset logic', () => {
      expect(getDefaultValueForField('unknown', domainPropertiesFromApi)).toBe('');
    });

    it('falsy entity → empty default', () => {
      expect(getDefaultValueForField('smsDomain', null)).toBe('');
    });

    it('returns emailReplyToId default for the selected domain', () => {
      // Covers line 277: if (fieldKey === 'emailReplyToId') return defs.replyToId branch
      const ctx = { fieldValues: { emailDomain: 'e1' } };
      expect(getDefaultValueForField('emailReplyToId', domainPropertiesFromApi, ctx)).toBe('support@brand.com');
    });

    it('returns emailSenderName default for the selected domain', () => {
      const ctx = { fieldValues: { emailDomain: 'e1' } };
      expect(getDefaultValueForField('emailSenderName', domainPropertiesFromApi, ctx)).toBe('Brand');
    });

    it('returns emailSenderId default for the selected domain', () => {
      const ctx = { fieldValues: { emailDomain: 'e1' } };
      expect(getDefaultValueForField('emailSenderId', domainPropertiesFromApi, ctx)).toBe('noreply@brand.com');
    });
  });

  describe('internal helper branches — contactInfo, domain shape, WhatsApp', () => {
    it('getValueFromContactInfo returns empty string when contactInfo is not an array', () => {
      // Covers line 45: !Array.isArray(contactInfo) → return ''
      const fieldWithNonArrayContactInfo = {
        SMS: [{ domainProperties: { id: 'x', contactInfo: { type: 'gsm_sender_id', value: '+bad' } } }],
      };
      const fields = getFieldsForChannels(['SMS']);
      const senderField = fields.find((f) => f.fieldKey === 'smsSenderId');
      // Should not throw and should return ''
      expect(senderField.getValue(fieldWithNonArrayContactInfo, {})).toBe('');
    });

    it('getOptionsFromContactInfo returns [] when contactInfo is a non-array object', () => {
      // Covers line 60: !Array.isArray(contactInfo) → return []
      const entity = {
        SMS: [{ domainProperties: { id: 'y', contactInfo: { type: 'gsm_sender_id', value: '+bad' } } }],
      };
      const senderField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsSenderId');
      expect(senderField.getOptions(entity)).toEqual([]);
    });

    it('getSmsDomainById returns first domain when domainId is null', () => {
      // Covers line 83: domainId == null → return arr[0]
      const result = getSmsDefaultsForDomainId(domainPropertiesFromApi, null);
      // Should return defaults for the first SMS gateway
      expect(result.senderId).toBe('+1001');
    });

    it('getSmsDomainById falls back to arr[0] when domainId does not match any domain', () => {
      // Covers line 88: || arr[0] || null fallback
      const result = getSmsDefaultsForDomainId(domainPropertiesFromApi, 'no-match-id');
      expect(result.senderId).toBe('+1001');
    });

    it('getSmsDomainOptions uses String(index) as value when no id fields exist on domain', () => {
      // Covers line 97: d.domainId ?? d.id ?? String(i) → String(i) for index fallback
      const entityNoId = {
        SMS: [
          { domainProperties: { domainName: 'No-ID Gateway', contactInfo: [] } },
        ],
      };
      const domainField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsDomain');
      const opts = domainField.getOptions(entityNoId);
      expect(opts[0].value).toBe('0'); // String(index 0)
    });

    it('getSmsDomainOptions uses hostName as label fallback when domainName is absent', () => {
      // Covers label fallback: domainProperties?.hostName branch
      const entityHostname = {
        SMS: [
          { domainProperties: { id: 's-h', hostName: 'smtp.brand.com', contactInfo: [] } },
        ],
      };
      const domainField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsDomain');
      const opts = domainField.getOptions(entityHostname);
      expect(opts[0].label).toBe('smtp.brand.com');
    });

    it('getSmsDomainOptions deduplicates entries with the same label', () => {
      // Covers line 99: !seen.has(label) deduplication
      const entityDuplicate = {
        SMS: [
          { domainProperties: { id: 's-a', domainName: 'Same Name', contactInfo: [] } },
          { domainProperties: { id: 's-b', domainName: 'Same Name', contactInfo: [] } },
        ],
      };
      const domainField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsDomain');
      const opts = domainField.getOptions(entityDuplicate);
      expect(opts.length).toBe(1);
      expect(opts[0].label).toBe('Same Name');
    });

    it('getDomainSourceAccountId uses sourceAccountIdentifier when wabaId is absent', () => {
      // Covers line 299: connectionProperties?.wabaId || connectionProperties?.sourceAccountIdentifier
      const entityWithSourceId = {
        WHATSAPP: [{
          domainProperties: {
            domainName: 'WA Source',
            connectionProperties: { sourceAccountIdentifier: 'src-acc-1' },
            contactInfo: [{ type: 'gsm_sender_id', value: '+w1', valid: true, default: true }],
          },
        }],
      };
      expect(getWhatsappAccountName(entityWithSourceId, 'src-acc-1')).toBe('WA Source');
    });

    it('getWhatsappAccountName returns first domain when sourceAccountId is null/empty', () => {
      // Covers fallback branch in getWhatsappDomainBySourceAccount
      const entity = {
        WHATSAPP: [{
          domainProperties: {
            domainName: 'First WA',
            connectionProperties: {},
            contactInfo: [{ type: 'gsm_sender_id', value: '+w2', valid: true, default: true }],
          },
        }],
      };
      expect(getWhatsappAccountName(entity, null)).toBe('First WA');
      expect(getWhatsappAccountName(entity, '')).toBe('First WA');
    });

    it('parseEntityForDisplay returns all channel defaults together in a combined entity', () => {
      // Covers the full parseEntityForDisplay with combined entity — all channel branches hit
      const summary = parseEntityForDisplay(domainPropertiesFromApi, { whatsappSourceAccountId: 'waba-99' });
      expect(summary.smsDomain).toBeTruthy();
      expect(summary.emailDomain).toBeTruthy();
      expect(summary.whatsappSenderNumber).toBe('+wa1');
      expect(summary.rcsSenderNumber).toBe('+rcs1');
      expect(summary.viberSenderId).toBe('viber-sender-1');
      expect(summary.zaloSenderId).toBe('+z1');
      expect(summary.lineSenderId).toBe('+line1');
    });

    it('email domain name display uses hostName as fallback when domainName is absent', () => {
      // Covers getEmailDomainNameForDisplay hostName branch
      const entity = {
        EMAIL: [{
          domainProperties: { id: 'e-h', hostName: 'mail.company.com', contactInfo: [] },
        }],
      };
      const summary = parseEntityForDisplay(entity);
      expect(summary.emailDomain).toBe('mail.company.com');
    });

    it('email sender name from options uses label-then-value fallback', () => {
      // Covers getEmailSenderNameOptions: label || value and value || label chains
      const entity = {
        EMAIL: [{
          domainProperties: {
            id: 'e-ln',
            contactInfo: [
              // Has value but no label — label should fall back to value
              { type: 'sender_id', value: 'no-label@co.com', valid: true, default: true },
            ],
          },
        }],
      };
      const senderNameField = getFieldsForChannels(['EMAIL']).find((f) => f.fieldKey === 'emailSenderName');
      const opts = senderNameField.getOptions(entity);
      // Should still produce an option using value as label
      expect(opts.length).toBeGreaterThan(0);
    });

    it('buildChannelSettingFromFieldValues with only ZALO data produces only ZALO key', () => {
      const result = buildChannelSettingFromFieldValues({ zaloSenderId: 'zs1' });
      expect(result).toEqual({ ZALO: { zaloSenderId: 'zs1' } });
    });

    it('buildChannelSettingFromFieldValues with only LINE data produces only LINE key', () => {
      const result = buildChannelSettingFromFieldValues({ lineSenderId: 'ls1' });
      expect(result).toEqual({ LINE: { lineSenderId: 'ls1' } });
    });

    it('buildChannelSettingFromFieldValues with only RCS data produces only RCS key', () => {
      const result = buildChannelSettingFromFieldValues({ rcsSenderNumber: '+rcs-x' });
      expect(result).toEqual({ RCS: { senderMobNum: '+rcs-x', rcsSender: '+rcs-x' } });
    });

    it('hasDomainGateway returns false for an unknown channel when entity is empty', () => {
      expect(hasDomainGateway({}, SMS)).toBe(false);
      expect(hasDomainGateway({}, EMAIL)).toBe(false);
      expect(hasDomainGateway({}, RCS)).toBe(false);
    });

    it('toArray passes through arrays unchanged', () => {
      // Validate array→array passthrough in toArray via getSmsDomainOptions
      const entity = {
        SMS: [
          { domainProperties: { id: 'arr-1', domainName: 'Array GW', contactInfo: [] } },
        ],
      };
      const domainField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsDomain');
      expect(domainField.getOptions(entity).length).toBe(1);
    });

    it('getChannelData returns null when entity has no matching channel key', () => {
      // Covers getChannelData returning null → functions returning empty defaults
      const emptyEntity = {};
      expect(getSmsDefaultsForDomainId(emptyEntity, 'x')).toEqual({ senderId: '' });
    });

    it('contactInfo entry with no value but a valid label falls back to label in options', () => {
      // Covers getOptionsFromContactInfo: val = m.value || m.label || ''
      const entityLabelOnly = {
        SMS: [{
          domainProperties: {
            id: 'lbl',
            contactInfo: [
              { type: 'gsm_sender_id', label: 'label-only-sender', valid: true, default: true },
            ],
          },
        }],
      };
      const senderField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsSenderId');
      const opts = senderField.getOptions(entityLabelOnly);
      expect(opts[0].value).toBe('label-only-sender');
    });

    it('getEmailDomainById returns first domain when domainId is null', () => {
      // Covers email version of line 144: domainId == null → arr[0]
      const result = getEmailDefaultsForDomainId(domainPropertiesFromApi, null);
      expect(result.senderId).toBe('noreply@brand.com');
    });

    it('getEmailDomainById falls back to arr[0] when domainId has no match', () => {
      // Covers email fallback: find() || arr[0]
      const result = getEmailDefaultsForDomainId(domainPropertiesFromApi, 'nonexistent-domain-id');
      expect(result.senderId).toBe('noreply@brand.com');
    });

    it('getEmailSenderIdOptions uses current entity email data when no domain selected in form', () => {
      // Covers line 184: selectedDomainId ? ... : getEmailData(entity) branch (falsy selectedDomainId)
      const emailField = getFieldsForChannels(['EMAIL']).find((f) => f.fieldKey === 'emailSenderId');
      const opts = emailField.getOptions(domainPropertiesFromApi, { fieldValues: {} });
      expect(opts.some((o) => o.value === 'noreply@brand.com')).toBe(true);
    });

    it('getEmailSenderNameOptions with contact having only value (no label) uses value as display', () => {
      // Covers getEmailSenderNameOptions: contact?.label || contact?.value — label absent
      const entity = {
        EMAIL: [{
          domainProperties: {
            id: 'e-val',
            contactInfo: [
              { type: 'sender_id', value: 'sender@domain.com', valid: true, default: true },
            ],
          },
        }],
      };
      const senderNameField = getFieldsForChannels(['EMAIL']).find((f) => f.fieldKey === 'emailSenderName');
      const opts = senderNameField.getOptions(entity, { fieldValues: {} });
      expect(opts[0].value).toBe('sender@domain.com');
    });

    it('getEmailReplyToIdOptions uses current email domain when no domain selected in form', () => {
      // Covers getEmailReplyToIdOptions: falsy selectedDomainId → getEmailData
      const replyField = getFieldsForChannels(['EMAIL']).find((f) => f.fieldKey === 'emailReplyToId');
      const opts = replyField.getOptions(domainPropertiesFromApi, { fieldValues: {} });
      expect(opts.some((o) => o.value === 'support@brand.com')).toBe(true);
    });

    it('getRcsAccountName uses domainName from root when domainProperties is absent', () => {
      // Covers rcsData.domainName || rcsData.label fallback
      const entity = {
        RCS: [{ domainName: 'Root RCS Name', domainProperties: { contactInfo: [] } }],
      };
      expect(getRcsAccountName(entity)).toBe('Root RCS Name');
    });

    it('getWhatsappDomainBySourceAccount falls back to first domain when sourceAccountId matches nothing', () => {
      // Covers line 306: find() || arr[0] fallback
      const entity = {
        WHATSAPP: [{
          domainProperties: {
            domainName: 'Only WA Domain',
            connectionProperties: { sourceAccountIdentifier: 'different-id' },
            contactInfo: [{ type: 'gsm_sender_id', value: '+wa-only', valid: true, default: true }],
          },
        }],
      };
      expect(getWhatsappAccountName(entity, 'not-matching-id')).toBe('Only WA Domain');
    });

    it('getDomainSourceAccountId uses userid as final fallback', () => {
      // Covers line 299: userid fallback
      const entity = {
        WHATSAPP: [{
          domainProperties: {
            domainName: 'WA userid',
            connectionProperties: { userid: 'user-acc-1' },
            contactInfo: [{ type: 'gsm_sender_id', value: '+wuid', valid: true, default: true }],
          },
        }],
      };
      expect(getWhatsappAccountName(entity, 'user-acc-1')).toBe('WA userid');
    });

    it('getViberDomainId returns domainId/id root fields when domainProperties.id is 0', () => {
      // Covers line 354-355: dpId === 0 → d.domainId ?? d.id
      const entityViberZeroId = {
        VIBER: [{
          domainId: 'vdomId',
          domainProperties: { id: 0, domainName: 'Viber Zero', contactInfo: [] },
        }],
      };
      const viberAccountField = getFieldsForChannels(['VIBER']).find((f) => f.fieldKey === 'viberAccount');
      const val = viberAccountField.getValue(entityViberZeroId);
      expect(val).toBe('vdomId');
    });

    it('reduce short-circuits when preferred type is already found (no fallback iteration)', () => {
      // Covers getValueFromContactInfo: `if (found) return found` short-circuit in reduce
      const entityBothTypes = {
        SMS: [{
          domainProperties: {
            id: 'both',
            contactInfo: [
              { type: 'gsm_sender_id', value: '+gsm', valid: true, default: true },
              { type: 'cdma_sender_id', value: '+cdma', valid: true, default: false },
            ],
          },
        }],
      };
      const senderField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsSenderId');
      // GSM exists, so CDMA should not be used
      expect(senderField.getValue(entityBothTypes, {})).toBe('+gsm');
    });

    it('getOptionsFromContactInfo deduplicates values across contactInfo entries', () => {
      // Covers seen.has(val) deduplication branch in getOptionsFromContactInfo
      const entityDupeValues = {
        SMS: [{
          domainProperties: {
            id: 'dupe',
            contactInfo: [
              { type: 'gsm_sender_id', value: '+same', valid: true },
              { type: 'gsm_sender_id', value: '+same', valid: true },
            ],
          },
        }],
      };
      const senderField = getFieldsForChannels(['SMS']).find((f) => f.fieldKey === 'smsSenderId');
      const opts = senderField.getOptions(entityDupeValues);
      expect(opts.filter((o) => o.value === '+same').length).toBe(1);
    });

    it('getEmailDefaultsForDomain returns empty object when domainData is null', () => {
      // Covers line 240: if (!domainData) return empty defaults
      const result = getEmailDefaultsForDomainId({ EMAIL: [] }, 'any-id');
      expect(result).toEqual({ senderId: '', senderName: '', replyToId: '' });
    });

    it('getEmailDefaultsForDomain returns empty strings when domain has no sender_id or reply_to_id entries', () => {
      // Covers the ternary false branches: senderMatch ? ... : '' and replyMatch ? ... : ''
      const result = getEmailDefaultsForDomainId({
        EMAIL: [{
          domainProperties: {
            id: 'e-no-sender',
            contactInfo: [
              { type: 'gsm_sender_id', value: '+111', valid: true },
            ],
          },
        }],
      }, 'e-no-sender');
      expect(result).toEqual({ senderId: '', senderName: '', replyToId: '' });
    });

    it('getEmailDefaultsForDomain uses label fallback for senderId and replyToId when value is absent', () => {
      // Covers: (senderMatch.value || senderMatch.label) and (replyMatch.value || replyMatch.label)
      // when .value is null/falsy and .label provides the fallback
      const result = getEmailDefaultsForDomainId({
        EMAIL: [{
          domainProperties: {
            id: 'e-label-only',
            contactInfo: [
              {
                type: 'sender_id', label: 'Brand Mailer', value: null, valid: true, default: true,
              },
              {
                type: 'reply_to_id', label: 'support@brand.com', value: null, valid: true, default: true,
              },
            ],
          },
        }],
      }, 'e-label-only');
      expect(result.senderId).toBe('Brand Mailer');
      expect(result.replyToId).toBe('support@brand.com');
    });

    it('getEmailDefaultsForDomain uses value fallback for senderName when label is absent', () => {
      // Covers: (senderMatch.label || senderMatch.value) when .label is null/falsy
      const result = getEmailDefaultsForDomainId({
        EMAIL: [{
          domainProperties: {
            id: 'e-value-only',
            contactInfo: [
              {
                type: 'sender_id', value: 'noreply@brand.com', label: null, valid: true, default: true,
              },
            ],
          },
        }],
      }, 'e-value-only');
      expect(result.senderName).toBe('noreply@brand.com');
    });

    it('getEmailDomainOptions uses index as value when all id fields are absent', () => {
      // Covers line 158: d.domainId ?? d.id ?? String(i) → String(i)
      const entity = {
        EMAIL: [
          { domainProperties: { domainName: 'Email No ID', contactInfo: [] } },
        ],
      };
      const domainField = getFieldsForChannels(['EMAIL']).find((f) => f.fieldKey === 'emailDomain');
      const opts = domainField.getOptions(entity);
      expect(opts[0].value).toBe('0');
    });

    it('parseEntityForDisplay returns RCS-only summary correctly', () => {
      // Covers RCS-only branch in parseEntityForDisplay
      const rcsOnly = {
        RCS: [{
          domainProperties: {
            domainName: 'RCS-only',
            contactInfo: [{ type: 'gsm_sender_id', value: '+rcs-o', valid: true, default: true }],
          },
        }],
      };
      const summary = parseEntityForDisplay(rcsOnly);
      expect(summary.rcsSenderNumber).toBe('+rcs-o');
      expect(summary.senderNumber).toBe('+rcs-o');
    });

    it('buildChannelSettingFromFieldValues with only VIBER data produces only VIBER key', () => {
      const result = buildChannelSettingFromFieldValues({ viberAccount: 'va1', viberSenderId: 'vs1' });
      expect(result).toEqual({ VIBER: { domainId: 'va1', sender: 'vs1', gsmSenderId: 'vs1' } });
    });

    it('parseChannelSettingForDisplay handles missing VIBER sub-fields gracefully', () => {
      // Covers fallback branches in parseChannelSettingForDisplay VIBER section
      const flat = parseChannelSettingForDisplay({ VIBER: { domainId: 'v1' } });
      expect(flat.viberAccount).toBe('v1');
      // viberSenderId is undefined when no sender fields present (not in the mapping)
      expect(flat.viberSenderId).toBeFalsy();
    });
  });

  describe('getViberAccountOptions — synthetic fallback prepend', () => {
    it('prepends a synthetic entry when the saved viberAccount is absent from API options (stale saved domain)', () => {
      // Triggers the prepend path: context.fieldValues.viberAccount is not present in API options
      const entityWithActiveDomain = {
        VIBER: [{
          domainProperties: {
            id: 5,
            domainName: 'Current Domain',
            contactInfo: [],
          },
        }],
      };
      const contextWithStaleSave = { fieldValues: { viberAccount: 'old-deactivated-domain' } };
      const viberAccountField = getFieldsForChannels(['VIBER']).find((fieldConfig) => fieldConfig.fieldKey === 'viberAccount');
      const opts = viberAccountField.getOptions(entityWithActiveDomain, contextWithStaleSave);
      expect(opts[0].value).toBe('old-deactivated-domain');
      expect(opts.some((option) => option.value === 5)).toBe(true);
    });

    it('uses the first domain name as the prepended entry label when available', () => {
      const entityWithActiveDomain = {
        VIBER: [{
          domainProperties: {
            id: 5,
            domainName: 'Active Domain',
            contactInfo: [],
          },
        }],
      };
      const contextWithStaleSave = { fieldValues: { viberAccount: 'stale-account-123' } };
      const viberAccountField = getFieldsForChannels(['VIBER']).find((fieldConfig) => fieldConfig.fieldKey === 'viberAccount');
      const opts = viberAccountField.getOptions(entityWithActiveDomain, contextWithStaleSave);
      expect(opts[0]).toEqual({ label: 'Active Domain', value: 'stale-account-123' });
    });

    it('falls back to String(currentVal) as label when firstDomain has no domainName', () => {
      const entityNoDomainName = {
        VIBER: [{
          domainProperties: { id: 5, contactInfo: [] },
        }],
      };
      const contextWithStaleSave = { fieldValues: { viberAccount: 'stale-456' } };
      const viberAccountField = getFieldsForChannels(['VIBER']).find((fieldConfig) => fieldConfig.fieldKey === 'viberAccount');
      const opts = viberAccountField.getOptions(entityNoDomainName, contextWithStaleSave);
      expect(opts[0]).toEqual({ label: 'stale-456', value: 'stale-456' });
    });

    it('does not prepend when the saved account is already present in the API options', () => {
      const entityWithSingleDomain = {
        VIBER: [{
          domainProperties: {
            id: 99,
            domainName: 'Viber 99',
            contactInfo: [],
          },
        }],
      };
      const viberAccountField = getFieldsForChannels(['VIBER']).find((fieldConfig) => fieldConfig.fieldKey === 'viberAccount');
      const opts = viberAccountField.getOptions(entityWithSingleDomain, {});
      expect(opts.some((option) => option.value === 99)).toBe(true);
      expect(opts.length).toBe(1);
    });
  });

  describe('getSenderIdOptionsFromContactInfo — synthetic fallback prepend', () => {
    it('prepends a synthetic option when the saved sender ID is absent from derived contact list', () => {
      // Covers line 409-411: getSenderIdOptionsFromContactInfo synthetic prepend
      // This happens when the saved currentVal from getChannelData is not in the options list
      // For VIBER with viber_sender_id in contactInfo but getChannelData returns a different one
      const entityViberMismatch = {
        VIBER: [
          {
            id: 'vgw-1',
            domainProperties: {
              id: 0,
              domainName: 'Viber GW',
              contactInfo: [
                // Only viber_sender_id — gsm_sender_id is absent
                // getSenderIdFromContactInfo prefers gsm, falls back to cdma, then viber_sender_id
                // If there's a saved value as viber_sender_id but not in options...
                { type: 'viber_sender_id', value: 'viber-acc', valid: true, default: true },
              ],
            },
          },
        ],
      };

      const senderIdField = getFieldsForChannels(['VIBER']).find((f) => f.fieldKey === 'viberSenderId');
      const opts = senderIdField.getOptions(entityViberMismatch);
      // viber-acc should be in options via fallback
      expect(opts.some((o) => o.value === 'viber-acc')).toBe(true);
    });

    it('aggregates ZALO senders and does NOT prepend when current value is in the list', () => {
      // Covers the else branch of the synthetic prepend: currentVal IS in options → returns as-is
      const entityZalo = {
        ZALO: [
          {
            domainProperties: {
              id: 'z1',
              contactInfo: [
                { type: 'gsm_sender_id', value: 'zalo-sender', valid: true, default: true },
              ],
            },
          },
        ],
      };
      const senderIdField = getFieldsForChannels(['ZALO']).find((f) => f.fieldKey === 'zaloSenderId');
      const opts = senderIdField.getOptions(entityZalo);
      expect(opts.map((o) => o.value)).toContain('zalo-sender');
      // Should not have duplicates
      expect(opts.filter((o) => o.value === 'zalo-sender').length).toBe(1);
    });
  });
});
