import { ChatMarkdownService } from './chat-markdown.service';

describe('ChatMarkdownService', () => {
  let service: ChatMarkdownService;

  beforeEach(() => {
    service = new ChatMarkdownService();
  });

  describe('applyInline', () => {
    it('wraps selected text with the token', () => {
      const result = service.applyInline('hello world', { start: 6, end: 11 }, '**');

      expect(result.text).toBe('hello **world**');
      expect(result.selectionStart).toBe(result.selectionEnd);
      expect(result.selectionStart).toBe(result.text.length);
    });

    it('inserts empty token pair with the cursor between markers when nothing is selected', () => {
      const result = service.applyInline('', { start: 0, end: 0 }, '**');

      expect(result.text).toBe('****');
      expect(result.selectionStart).toBe(2);
      expect(result.selectionEnd).toBe(2);
    });
  });

  describe('applyPrefix', () => {
    it('prefixes each selected line', () => {
      const result = service.applyPrefix('line one\nline two', { start: 0, end: 17 }, '> ');

      expect(result.text).toBe('> line one\n> line two');
      expect(result.selectionStart).toBe(result.text.length);
    });

    it('inserts only the prefix with the cursor after it when nothing is selected', () => {
      const result = service.applyPrefix('', { start: 0, end: 0 }, '> ');

      expect(result.text).toBe('> ');
      expect(result.selectionStart).toBe(2);
      expect(result.selectionEnd).toBe(2);
    });
  });

  describe('applyHeading', () => {
    it('wraps selected text as a heading', () => {
      const result = service.applyHeading('intro\nTitle here\noutro', { start: 6, end: 16 }, 2);

      expect(result.text).toBe('intro\n## Title here\noutro');
    });

    it('inserts only the heading marker and space when nothing is selected', () => {
      const result = service.applyHeading('', { start: 0, end: 0 }, 1);

      expect(result.text).toBe('# ');
      expect(result.selectionStart).toBe(2);
      expect(result.selectionEnd).toBe(2);
    });
  });

  describe('applyOrderedList', () => {
    it('numbers each selected line', () => {
      const result = service.applyOrderedList('alpha\nbeta', { start: 0, end: 10 });

      expect(result.text).toBe('1. alpha\n2. beta');
    });

    it('inserts only the first list marker when nothing is selected', () => {
      const result = service.applyOrderedList('', { start: 0, end: 0 });

      expect(result.text).toBe('1. ');
      expect(result.selectionStart).toBe(3);
      expect(result.selectionEnd).toBe(3);
    });
  });

  describe('applyCodeBlock', () => {
    it('wraps selected text in a fenced code block', () => {
      const result = service.applyCodeBlock('before\nconst x = 1;\nafter', { start: 7, end: 19 });

      expect(result.text).toBe('before\n```\nconst x = 1;\n```\n\n\nafter');
    });

    it('inserts an empty fenced block with the cursor inside when nothing is selected', () => {
      const result = service.applyCodeBlock('', { start: 0, end: 0 });

      expect(result.text).toBe('```\n\n```\n\n');
      expect(result.selectionStart).toBe(4);
      expect(result.selectionEnd).toBe(4);
    });
  });

  describe('applyLink', () => {
    it('wraps selected text as link label and places the cursor in the url slot', () => {
      const result = service.applyLink('Visit docs', { start: 6, end: 10 });

      expect(result.text).toBe('Visit [docs]()');
      expect(result.selectionStart).toBe(13);
      expect(result.selectionEnd).toBe(13);
    });

    it('inserts empty link syntax with the cursor inside the label when nothing is selected', () => {
      const result = service.applyLink('', { start: 0, end: 0 });

      expect(result.text).toBe('[]()');
      expect(result.selectionStart).toBe(1);
      expect(result.selectionEnd).toBe(1);
    });
  });

  describe('applyImage', () => {
    it('wraps selected text as image alt text and places the cursor in the url slot', () => {
      const result = service.applyImage('logo', { start: 0, end: 4 });

      expect(result.text).toBe('![logo]()');
      expect(result.selectionStart).toBe(8);
      expect(result.selectionEnd).toBe(8);
    });

    it('inserts empty image syntax with the cursor inside the alt text when nothing is selected', () => {
      const result = service.applyImage('', { start: 0, end: 0 });

      expect(result.text).toBe('![]()');
      expect(result.selectionStart).toBe(2);
      expect(result.selectionEnd).toBe(2);
    });
  });

  describe('applyHorizontalRule', () => {
    it('inserts a horizontal rule without placeholder text', () => {
      const result = service.applyHorizontalRule('hello', { start: 5, end: 5 });

      expect(result.text).toBe('hello\n\n---\n\n');
      expect(result.selectionStart).toBe(result.text.length);
    });
  });
});
