import { describe, it, expect } from 'vitest';
import { CopyMeThatTxtParser } from '../CopyMeThatTxtParser.js';

const parser = new CopyMeThatTxtParser();

describe('CopyMeThatTxtParser', () => {
  describe('parseRecipe', () => {
    it('parses a complete TXT recipe', () => {
      const content = `
Chocolate Chip Cookies
Adapted from https://example.com/cookies
tags: Dessert, Cookies
I made this
Servings: 24

INGREDIENTS
1 cup flour
2 cups chocolate chips
1 tsp vanilla

STEPS
1) Mix dry ingredients
2) Add wet ingredients
3) Bake at 350°F for 10 minutes

NOTES
Use dark chocolate chips for best results.
`.trim();
      const result = parser.parseRecipe(content);
      expect(result).not.toBeNull();
      expect(result!.title).toBe('Chocolate Chip Cookies');
      expect(result!.sourceUrl).toBe('https://example.com/cookies');
      expect(result!.tags).toEqual(['Dessert', 'Cookies']);
      expect(result!.made).toBe(true);
      expect(result!.servings).toBe('24');
      expect(result!.ingredients).toEqual([
        '1 cup flour',
        '2 cups chocolate chips',
        '1 tsp vanilla',
      ]);
      expect(result!.instructions).toEqual([
        'Mix dry ingredients',
        'Add wet ingredients',
        'Bake at 350°F for 10 minutes',
      ]);
      expect(result!.notes).toBe('Use dark chocolate chips for best results.');
    });

    it('returns null for too short content', () => {
      expect(parser.parseRecipe('short')).toBeNull();
    });

    it('returns null if title missing (empty first line)', () => {
      const content = '\nServings: 2\n\nINGREDIENTS\na\n\nSTEPS\nb';
      expect(parser.parseRecipe(content)).toBeNull();
    });

    it('returns null if no ingredients', () => {
      const content = `
Test Recipe

INGREDIENTS

STEPS
Step 1
`.trim();
      expect(parser.parseRecipe(content)).toBeNull();
    });

    it('returns null if no steps', () => {
      const content = `
Test Recipe

INGREDIENTS
ing1

STEPS
`.trim();
      expect(parser.parseRecipe(content)).toBeNull();
    });

    it('handles all optional sections missing', () => {
      const content = `
Simple Title

INGREDIENTS
a

STEPS
b
`.trim();
      const result = parser.parseRecipe(content);
      expect(result).not.toBeNull();
      expect(result!.sourceUrl).toBeUndefined();
      expect(result!.tags).toEqual([]);
      expect(result!.made).toBe(false);
      expect(result!.servings).toBeUndefined();
      expect(result!.notes).toBeUndefined();
    });

    it('trims whitespace from lines and skips empties', () => {
      const content = `
Title

  Adapted from http://test.com
tags: one, two
I made this
Servings: 4

INGREDIENTS
  item 1

  item 2

STEPS
  1) Do thing

  2) Another thing
`.trim();
      const result = parser.parseRecipe(content);
      expect(result!.sourceUrl).toBe('http://test.com');
      expect(result!.tags).toEqual(['one', 'two']);
      expect(result!.made).toBe(true);
      expect(result!.servings).toBe('4');
      expect(result!.ingredients).toEqual(['item 1', 'item 2']);
      expect(result!.instructions).toEqual(['Do thing', 'Another thing']);
    });

    it('removes leading numbers from instructions', () => {
      const content = `
Title

INGREDIENTS
x

STEPS
1) First
2) Second
3) Third
`.trim();
      const result = parser.parseRecipe(content);
      expect(result!.instructions).toEqual(['First', 'Second', 'Third']);
    });

    it('handles multiple blank lines in notes', () => {
      const content = `
Title

INGREDIENTS
x

STEPS
s

NOTES

Note line 1

Note line 2
`.trim();
      const result = parser.parseRecipe(content);
      expect(result!.notes).toBe('Note line 1\n\nNote line 2');
    });

    it('parses tags with varying whitespace', () => {
      const content = `
Title
tags:  a , b ,  c
INGREDIENTS
x
STEPS
y
`.trim();
      const result = parser.parseRecipe(content);
      expect(result!.tags).toEqual(['a', 'b', 'c']);
    });
  });

  describe('toCreateRecipeInput', () => {
    it('maps parsed fields correctly', () => {
      const parsed = {
        title: 'Test',
        sourceUrl: 'https://src',
        tags: ['Tag1'],
        made: true,
        servings: '4 servings',
        ingredients: ['a', 'b'],
        instructions: ['x', 'y'],
        notes: 'note',
      };
      const input = parser.toCreateRecipeInput(parsed);
      expect(input.title).toBe('Test');
      expect(input.source_url).toBe('https://src');
      expect(input.made).toBe(true);
      expect(input.servings).toBe(4);
      expect(input.ingredients).toHaveLength(2);
      expect(input.steps).toHaveLength(2);
      expect(input.notes).toBe('note');
    });

    it('extracts numeric servings correctly', () => {
      const parsed = { servings: '6 servings', ingredients: [], instructions: [], title: '', tags: [], made: false };
      const input = parser.toCreateRecipeInput(parsed);
      expect(input.servings).toBe(6);
    });

    it('handles missing servings (undefined)', () => {
      const parsed = { ingredients: [], instructions: [], title: '', tags: [], made: false };
      const input = parser.toCreateRecipeInput(parsed);
      expect(input.servings).toBeUndefined();
    });
  });
});
