import { describe, expect, it } from 'vitest';
import {
  countComponentsV2,
  decodeComponentCustomId,
  encodeComponentCustomId,
  emptyComponentsV2,
  mapComponentsV2TextFields,
  MessageComponentsV2Schema
} from './components-v2.js';

describe('MessageComponentsV2Schema', () => {
  it('accepts a minimal container + text display', () => {
    const parsed = MessageComponentsV2Schema.parse(emptyComponentsV2());
    expect(parsed.components).toHaveLength(1);
    expect(parsed.components[0]?.type).toBe('container');
  });

  it('accepts interactive button with matching action', () => {
    const parsed = MessageComponentsV2Schema.parse({
      components: [
        {
          type: 'action_row',
          components: [
            {
              type: 'button',
              style: 'Primary',
              label: 'Toggle',
              actionId: 'toggle_vip'
            }
          ]
        }
      ],
      actions: {
        toggle_vip: { type: 'TOGGLE_ROLE', roleId: '123456789012345678' }
      }
    });
    expect(parsed.actions.toggle_vip?.type).toBe('TOGGLE_ROLE');
  });

  it('accepts link buttons without action', () => {
    const parsed = MessageComponentsV2Schema.parse({
      components: [
        {
          type: 'action_row',
          components: [
            {
              type: 'button',
              style: 'Link',
              label: 'Docs',
              url: 'https://example.com'
            }
          ]
        }
      ],
      actions: {}
    });
    expect(parsed.components[0]?.type).toBe('action_row');
  });

  it('rejects missing action definitions', () => {
    const result = MessageComponentsV2Schema.safeParse({
      components: [
        {
          type: 'action_row',
          components: [{ type: 'button', style: 'Success', label: 'Go', actionId: 'missing' }]
        }
      ],
      actions: {}
    });
    expect(result.success).toBe(false);
  });

  it('rejects trees above 40 components', () => {
    const texts = Array.from({ length: 41 }, (_, i) => ({
      type: 'text_display' as const,
      content: `Line ${i}`
    }));
    const result = MessageComponentsV2Schema.safeParse({
      components: texts,
      actions: {}
    });
    expect(result.success).toBe(false);
  });

  it('counts nested container children', () => {
    const count = countComponentsV2([
      {
        type: 'container',
        components: [
          { type: 'text_display', content: 'a' },
          { type: 'separator' },
          {
            type: 'section',
            text: 'hello',
            accessory: { type: 'thumbnail', url: 'https://example.com/a.png' }
          }
        ]
      }
    ]);
    // container + 3 children + section accessory
    expect(count).toBe(5);
  });
});

describe('custom_id helpers', () => {
  it('encodes and decodes cv2 custom ids', () => {
    const customId = encodeComponentCustomId('t', 'tag_abc', 'reply1');
    expect(customId).toBe('cv2:t:tag_abc:reply1');
    expect(decodeComponentCustomId(customId)).toEqual({
      source: 't',
      ref: 'tag_abc',
      actionId: 'reply1'
    });
  });

  it('returns null for unrelated custom ids', () => {
    expect(decodeComponentCustomId('sr:btn:1:2')).toBeNull();
  });
});

describe('mapComponentsV2TextFields', () => {
  it('maps text and action reply content', () => {
    const mapped = mapComponentsV2TextFields(
      {
        components: [
          {
            type: 'container',
            components: [{ type: 'text_display', content: 'Hi {user}' }]
          }
        ],
        actions: {
          a1: { type: 'EPHEMERAL_REPLY', content: 'Welcome {user}' }
        }
      },
      (value) => value.replaceAll('{user}', '@Mace')
    );
    const container = mapped.components[0];
    expect(container?.type).toBe('container');
    if (container?.type === 'container') {
      expect(container.components[0]).toMatchObject({
        type: 'text_display',
        content: 'Hi @Mace'
      });
    }
    expect(mapped.actions.a1?.content).toBe('Welcome @Mace');
  });
});
