import 'package:flutter_test/flutter_test.dart';
import 'package:ocideck/models/deck.dart';
import 'package:ocideck/models/settings.dart';
import 'package:ocideck/models/slide.dart';
import 'package:ocideck/services/markdown_service.dart';

void main() {
  test('round-trips image slide with title as image slide', () {
    final service = MarkdownService();
    final markdown = service.generateDeck(
      Deck(
        title: 'Demo',
        slides: [
          Slide.create(
            SlideType.image,
          ).copyWith(title: 'Overlay title', imagePath: 'images/photo.png'),
        ],
      ),
    );

    final deck = service.parseDeck(markdown);

    expect(deck, isNotNull);
    expect(deck!.slides.single.type, SlideType.image);
    expect(deck.slides.single.title, 'Overlay title');
    expect(deck.slides.single.imagePath, 'images/photo.png');
  });

  test('round-trips bulletsImage slide with image and size', () {
    final service = MarkdownService();
    final markdown = service.generateDeck(
      Deck(
        title: 'Demo',
        slides: [
          Slide.create(SlideType.bulletsImage).copyWith(
            title: 'Profiel',
            bullets: ['Eerste punt', '\tGenest punt'],
            imagePath: 'images/portret.png',
            imageCaption: 'Een onderschrift',
            imageSize: 45,
          ),
        ],
      ),
    );

    final deck = service.parseDeck(markdown);

    expect(deck, isNotNull);
    final slide = deck!.slides.single;
    expect(slide.type, SlideType.bulletsImage);
    expect(slide.title, 'Profiel');
    expect(slide.imagePath, 'images/portret.png');
    expect(slide.imageCaption, 'Een onderschrift');
    expect(slide.imageSize, 45);
    expect(slide.bullets, ['Eerste punt', '\tGenest punt']);
  });

  test('keeps a plain image inside free markdown as free markdown', () {
    final service = MarkdownService();
    final deck = service.parseDeck(
      '---\nmarp: true\ntheme: vigilis\n---\n\n'
      '![](images/inline.png)\n\nWat losse tekst.\n',
    );

    expect(deck, isNotNull);
    final slide = deck!.slides.single;
    expect(slide.type, SlideType.freeMarkdown);
    expect(slide.imagePath, isEmpty);
  });

  test('round-trips deck style profile', () {
    final service = MarkdownService();
    final profile = const ThemeProfile(
      name: 'Klant A',
      slideBackgroundColor: '#111827',
      textColor: '#F8FAFC',
      accentColor: '#F59E0B',
      tableTextColor: '#111111',
      tableHeaderTextColor: '#EEEEEE',
      logoPosition: 'top-left',
      logoSize: 120,
      fontFamily: 'Georgia',
      footerText: 'Vertrouwelijk · {page}/{total}',
      footerShowPageNumbers: true,
      footerPosition: 'center',
      closingSlideEnabled: true,
      closingSlideMarkdown: '# Einde\n\nDank voor jullie aandacht.',
    );

    // The style profile only travels inside the markdown when explicitly
    // inlined (transient beamer payloads); a plain save keeps the file clean.
    final markdown = service.generateDeck(
      Deck(
        title: 'Demo',
        themeProfile: profile,
        slides: [Slide.create(SlideType.title).copyWith(title: 'Demo')],
      ),
      inlineStyleProfile: true,
    );

    final deck = service.parseDeck(markdown);

    expect(deck, isNotNull);
    expect(deck!.themeProfile.name, 'Klant A');
    expect(deck.themeProfile.slideBackgroundColor, '#111827');
    expect(deck.themeProfile.tableTextColor, '#111111');
    expect(deck.themeProfile.tableHeaderTextColor, '#EEEEEE');
    expect(deck.themeProfile.logoPosition, 'top-left');
    expect(deck.themeProfile.logoSize, 120);
    expect(deck.themeProfile.fontFamily, 'Georgia');
    expect(deck.themeProfile.footerText, 'Vertrouwelijk · {page}/{total}');
    expect(deck.themeProfile.footerShowPageNumbers, isTrue);
    expect(deck.themeProfile.footerPosition, 'center');
    expect(deck.themeProfile.closingSlideEnabled, isTrue);
    expect(
      deck.themeProfile.closingSlideMarkdown,
      '# Einde\n\nDank voor jullie aandacht.',
    );
  });

  test('a saved deck does not embed the style profile', () {
    final service = MarkdownService();
    final markdown = service.generateDeck(
      Deck(
        title: 'Demo',
        themeProfile: const ThemeProfile(
          name: 'Klant A',
          slideBackgroundColor: '#111827',
        ),
        slides: [Slide.create(SlideType.title).copyWith(title: 'Demo')],
      ),
    );

    // The file is the base content only; styling stays out of it. Parsing it
    // back yields the default profile, not the one that was saved.
    expect(markdown.contains('ocideck_style_profile'), isFalse);
    final deck = service.parseDeck(markdown);
    expect(deck!.themeProfile.name, 'Standaard');
    expect(deck.themeProfile.slideBackgroundColor, isNot('#111827'));
  });

  test('adds logo-safe class when deck profile has logo', () {
    final service = MarkdownService();
    final markdown = service.generateDeck(
      Deck(
        title: 'Demo',
        themeProfile: const ThemeProfile(logoPath: '/tmp/logo.png'),
        slides: [
          Slide.create(
            SlideType.bullets,
          ).copyWith(title: 'Demo', bullets: ['Een lange bullet']),
        ],
      ),
    );

    expect(markdown, contains('<!-- _class: logo-safe -->'));
  });

  test('round-trips video slide with audio attachment', () {
    final service = MarkdownService();
    final markdown = service.generateDeck(
      Deck(
        title: 'Media',
        slides: [
          Slide.create(SlideType.video).copyWith(
            title: 'Film',
            videoPath: 'media/movie.mp4',
            videoAutoplay: true,
            audioPath: 'media/narration.mp3',
            audioAutoplay: true,
          ),
        ],
      ),
    );

    final deck = service.parseDeck(markdown);

    expect(deck, isNotNull);
    expect(deck!.slides.single.type, SlideType.video);
    expect(deck.slides.single.videoPath, 'media/movie.mp4');
    expect(deck.slides.single.videoAutoplay, isTrue);
    expect(deck.slides.single.audioPath, 'media/narration.mp3');
    expect(deck.slides.single.audioAutoplay, isTrue);
  });
}
