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

import 'package:flutter/material.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';

/// The canonical contract fixtures shared with the backend content validator
/// (see fixtures/README.md). Every one must parse into fully-typed nodes (no
/// PmUnknown in the content) and render in both themes without throwing.
const _fixtures = [
  'callout.json',
  'image.json',
  'kitchen-sink.json',
  'lists.json',
  'table.json',
  'text-marks.json',
];

Map<String, dynamic> _loadFixture(String name) {
  final raw = File(
    'test/widget/prosemirror/fixtures/$name',
  ).readAsStringSync();
  return jsonDecode(raw) as Map<String, dynamic>;
}

bool _hasUnknown(PmNode node) {
  if (node is PmUnknown) return true;
  return node.children.any(_hasUnknown);
}

Widget _host(PmNode doc, Brightness brightness) => MaterialApp(
  theme: ThemeData(
    colorScheme: ColorScheme.fromSeed(
      seedColor: const Color(0xFF993333),
      brightness: brightness,
    ),
  ),
  home: Scaffold(
    body: SingleChildScrollView(child: PmDocumentView(doc: doc)),
  ),
);

void main() {
  for (final fixture in _fixtures) {
    test('$fixture parses without any PmUnknown in its content', () {
      final doc = PmNode.fromJson(_loadFixture(fixture));
      // The root `doc` node itself has no dedicated subclass and maps to
      // PmUnknown by design; assert none of its content nodes are unknown.
      expect(doc, isA<PmUnknown>());
      expect(
        doc.children.any(_hasUnknown),
        isFalse,
        reason: '$fixture contains an unrecognised node type',
      );
    });

    testWidgets('$fixture renders in light + dark without exception', (
      tester,
    ) async {
      final doc = PmNode.fromJson(_loadFixture(fixture));

      await tester.pumpWidget(_host(doc, Brightness.light));
      await tester.pump();
      expect(tester.takeException(), isNull);

      await tester.pumpWidget(_host(doc, Brightness.dark));
      await tester.pump();
      expect(tester.takeException(), isNull);
    });
  }
}
