import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_layout_grid/flutter_layout_grid.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/widget/prosemirror/pm_document_view.dart';
import 'package:marianum_mobile/widget/prosemirror/pm_node.dart';
import 'package:marianum_mobile/widget/prosemirror/pm_table_view.dart';

PmNode _tableDoc() {
  final raw = File(
    'test/widget/prosemirror/fixtures/table.json',
  ).readAsStringSync();
  return PmNode.fromJson(jsonDecode(raw) as Map<String, dynamic>);
}

Widget _host(PmNode doc) => MaterialApp(
  home: Scaffold(
    body: SingleChildScrollView(child: PmDocumentView(doc: doc)),
  ),
);

PmTableCell _textCell(String text) => PmTableCell(
  children: [
    PmParagraph(children: [PmText(text: text)]),
  ],
);

void main() {
  setUp(() => pmTableMode.value = PmTableMode.scroll);
  tearDown(() => pmTableMode.value = PmTableMode.scroll);

  testWidgets('renders in every display mode without exception', (tester) async {
    await tester.pumpWidget(_host(_tableDoc()));

    for (final mode in PmTableMode.values) {
      pmTableMode.value = mode;
      await tester.pumpAndSettle();
      expect(tester.takeException(), isNull, reason: 'mode $mode threw');
    }
  });

  testWidgets('cells in a row share one height when wrapping', (tester) async {
    // One row, two cells: a short one and one long enough to wrap at the
    // constrained width. Both cell boxes must end up the same height.
    final doc = PmTable(
      children: [
        PmTableRow(
          children: [
            _textCell('kurz'),
            _textCell('ein deutlich laengerer Text der ganz sicher umbricht'),
          ],
        ),
      ],
    );

    pmTableMode.value = PmTableMode.wrap;
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Center(
            child: SizedBox(width: 200, child: PmDocumentView(doc: doc)),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();

    final boxes = find.descendant(
      of: find.byType(LayoutGrid),
      matching: find.byType(DecoratedBox),
    );
    expect(boxes, findsNWidgets(2));
    final first = tester.getSize(boxes.at(0)).height;
    final second = tester.getSize(boxes.at(1)).height;
    expect(first, greaterThan(0));
    expect(first, moreOrLessEquals(second, epsilon: 0.5));
  });

  testWidgets('tapping a toolbar button switches the shared mode', (
    tester,
  ) async {
    // The mode toolbar only renders once the table overflows its width — at the
    // full test surface the fixture table fits and the toggle stays hidden. Pin
    // a narrow width so it overflows, then let the post-frame overflow
    // measurement settle so the toolbar is present before tapping.
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: SingleChildScrollView(
            child: Center(
              child: SizedBox(width: 200, child: PmDocumentView(doc: _tableDoc())),
            ),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();
    expect(pmTableMode.value, PmTableMode.scroll);

    await tester.tap(find.byTooltip('Spalten umbrechen').first);
    await tester.pumpAndSettle();
    expect(pmTableMode.value, PmTableMode.wrap);

    await tester.tap(find.byTooltip('Verkleinern (alles auf einen Blick)').first);
    await tester.pumpAndSettle();
    expect(pmTableMode.value, PmTableMode.zoom);
  });
}
