import { describe, it, expect } from 'vitest';
import { formatScreenplay, getTemplate, getAllTemplates, elementTypeClass, formatLineForPreview, generateId } from './format';
import { detectElementType } from './detect';
import { ScreenplayElementType, TemplateType } from './types';

describe('generateId', () => {
  it('generates unique IDs', () => {
    const id1 = generateId();
    const id2 = generateId();
    expect(id1).not.toBe(id2);
    expect(id1.startsWith('el-')).toBe(true);
  });
});

describe('getTemplate', () => {
  it('returns standard template by default', () => {
    const template = getTemplate('standard');
    expect(template.name).toBe('standard');
    expect(template.fontFamily).toContain('Courier');
  });

  it('returns sitcom template', () => {
    const template = getTemplate('sitcom');
    expect(template.name).toBe('sitcom');
    expect(template.elementStyles.character.indentStart).toBe(2.0);
  });

  it('returns podcast template', () => {
    const template = getTemplate('podcast');
    expect(template.name).toBe('podcast');
    expect(template.elementStyles.character.bold).toBe(true);
  });

  it('getAllTemplates returns all three', () => {
    const templates = getAllTemplates();
    expect(templates).toHaveLength(3);
    expect(templates.map((t) => t.name)).toEqual(['standard', 'sitcom', 'podcast']);
  });
});

describe('elementTypeClass', () => {
  it('returns correct CSS class for each type', () => {
    expect(elementTypeClass('sceneHeading')).toBe('screenplay-sceneHeading');
    expect(elementTypeClass('dialogue')).toBe('screenplay-dialogue');
    expect(elementTypeClass('transition')).toBe('screenplay-transition');
  });
});

describe('formatScreenplay', () => {
  it('formats a simple screenplay', () => {
    const raw = `INT. LIVING ROOM - DAY

A cozy living room with a fireplace.

        JOHN
    Hello, world.

        MARY
    (smiling)
    Hi there.`;

    const result = formatScreenplay(raw, 'standard', detectElementType);
    expect(result.elements.length).toBeGreaterThan(0);
    expect(result.template).toBe('standard');

    const sceneHeading = result.elements.find((e) => e.type === 'sceneHeading');
    expect(sceneHeading).toBeDefined();
    expect(sceneHeading?.content).toContain('INT.');
  });

  it('handles empty input', () => {
    const result = formatScreenplay('', 'standard', detectElementType);
    expect(result.elements).toEqual([]);
  });

  it('groups consecutive same-type lines', () => {
    const raw = `        JOHN
    Line one.
    Line two.`;

    const result = formatScreenplay(raw, 'standard', detectElementType);
    const dialogueElements = result.elements.filter((e) => e.type === 'dialogue');
    expect(dialogueElements.length).toBe(1);
    const firstDialogue = dialogueElements[0];
    if (firstDialogue) {
      expect(firstDialogue.content).toContain('Line one');
      expect(firstDialogue.content).toContain('Line two');
    }
  });
});

describe('formatLineForPreview', () => {
  it('applies uppercase for scene headings', () => {
    const formatted = formatLineForPreview('int. room', 'sceneHeading', 'standard');
    expect(formatted).toContain('INT.');
  });

  it('adds indentation based on template', () => {
    const formatted = formatLineForPreview('JOHN', 'character', 'standard');
    expect(formatted.startsWith(' ')).toBe(true);
  });
});

describe('template element styles', () => {
  it('standard template has correct scene heading style', () => {
    const template = getTemplate('standard');
    const style = template.elementStyles.sceneHeading;
    expect(style.uppercase).toBe(true);
    expect(style.bold).toBe(true);
    expect(style.indentStart).toBe(0);
  });

  it('standard template has correct character style', () => {
    const template = getTemplate('standard');
    const style = template.elementStyles.character;
    expect(style.indentStart).toBe(3.7);
    expect(style.uppercase).toBe(true);
  });

  it('standard template has correct dialogue style', () => {
    const template = getTemplate('standard');
    const style = template.elementStyles.dialogue;
    expect(style.indentStart).toBe(2.5);
    expect(style.indentEnd).toBe(2.5);
  });

  it('standard template has correct transition style', () => {
    const template = getTemplate('standard');
    const style = template.elementStyles.transition;
    expect(style.textAlign).toBe('right');
    expect(style.uppercase).toBe(true);
  });
});
