import 'dart:convert';

import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:smplayer/core/infra/script_widget/widget_host_bridge.dart';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  test('sharedCache 按模块隔离且不读取旧全局缓存', () async {
    SharedPreferences.setMockInitialValues(<String, Object>{
      'smplayer.script_widget.shared_cache.widget-a': jsonEncode(
        <String, Object?>{'owner': 'widget-a', 'value': 1},
      ),
      'smplayer.script_widget.shared_cache.widget-b': jsonEncode(
        <String, Object?>{'owner': 'widget-b', 'value': 2},
      ),
      'smplayer.script_widget.shared_cache': jsonEncode(<String, Object?>{
        'owner': 'legacy-global',
      }),
    });
    final bridge = WidgetHostBridge();

    final widgetAData = await bridge.loadBootstrapData('widget-a');
    final widgetBData = await bridge.loadBootstrapData('widget-b');
    final widgetCData = await bridge.loadBootstrapData('widget-c');

    expect(widgetAData.sharedCache, <String, Object?>{
      'owner': 'widget-a',
      'value': 1,
    });
    expect(widgetBData.sharedCache, <String, Object?>{
      'owner': 'widget-b',
      'value': 2,
    });
    expect(widgetCData.sharedCache, isEmpty);
  });

  test('损坏的模块缓存不会污染其他模块的启动数据', () async {
    SharedPreferences.setMockInitialValues(<String, Object>{
      'smplayer.script_widget.shared_cache.invalid-widget': '{invalid',
      'smplayer.script_widget.shared_cache.valid-widget': jsonEncode(
        <String, Object?>{'ready': true},
      ),
    });
    final bridge = WidgetHostBridge();

    final invalidWidgetData = await bridge.loadBootstrapData('invalid-widget');
    final validWidgetData = await bridge.loadBootstrapData('valid-widget');

    expect(invalidWidgetData.sharedCache, isEmpty);
    expect(validWidgetData.sharedCache, <String, Object?>{'ready': true});
  });

  group('formatConsoleValue', () {
    test('展开 JS Error marker 为 name/message/stack 拼接', () {
      final formatted = formatConsoleValue(<String, Object?>{
        '__consoleErrorMarker': true,
        'name': 'TypeError',
        'message': '视频列表加载失败：网络超时',
        'stack': 'at getList (91porn_int.js:848)',
      });

      expect(
        formatted,
        'TypeError: 视频列表加载失败：网络超时\nat getList (91porn_int.js:848)',
      );
    });

    test('普通 Map 走 JSON 编码而不是 toString()', () {
      final formatted = formatConsoleValue(<String, Object?>{
        'status': 403,
        'reason': 'blocked',
      });

      expect(formatted, '{"status":403,"reason":"blocked"}');
    });

    test('字符串和基本类型保持原样', () {
      expect(formatConsoleValue('hello'), 'hello');
      expect(formatConsoleValue(42), '42');
      expect(formatConsoleValue(true), 'true');
      expect(formatConsoleValue(null), 'null');
    });
  });
}
