import 'dart:io';

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

void main() {
  group('脚本 HTTP 地址校验', () {
    test('允许公网 IPv4 与 IPv6 地址', () {
      expect(isPublicScriptAddress(InternetAddress('8.8.8.8')), isTrue);
      expect(
        isPublicScriptAddress(InternetAddress('2606:4700:4700::1111')),
        isTrue,
      );
    });

    test('拒绝真实威胁的 IPv4 地址（本机、LAN、云元数据、多播）', () {
      const blockedAddresses = <String>[
        '0.0.0.0',
        '10.0.0.1',
        '127.0.0.1',
        '169.254.169.254',
        '172.16.0.1',
        '192.0.0.1',
        '192.168.1.1',
        '224.0.0.1',
        '255.255.255.255',
      ];

      for (final address in blockedAddresses) {
        expect(
          isPublicScriptAddress(InternetAddress(address)),
          isFalse,
          reason: address,
        );
      }
    });

    test(
      '允许 CGNAT、文档、benchmark 段（代理 fake-ip 池会用到）',
      () {
        const allowedAddresses = <String>[
          '100.64.0.1', 
          '192.0.2.1', 
          '198.18.0.31', 
          '198.51.100.1', 
          '203.0.113.1', 
        ];

        for (final address in allowedAddresses) {
          expect(
            isPublicScriptAddress(InternetAddress(address)),
            isTrue,
            reason: address,
          );
        }
      },
    );

    test('拒绝 IPv6 回环、ULA、链路本地和 IPv4 映射回环', () {
      const blockedAddresses = <String>[
        '::',
        '::1',
        '::ffff:127.0.0.1',
        'fc00::1',
        'fd12:3456::1',
        'fe80::1',
      ];

      for (final address in blockedAddresses) {
        expect(
          isPublicScriptAddress(InternetAddress(address)),
          isFalse,
          reason: address,
        );
      }
    });

    test('允许 IPv6 文档段与 6to4 段（同样常见于 fake-ip 池）', () {
      const allowedAddresses = <String>[
        '2001:db8::1', 
        '2002::1', 
        '3fff::1', 
      ];

      for (final address in allowedAddresses) {
        expect(
          isPublicScriptAddress(InternetAddress(address)),
          isTrue,
          reason: address,
        );
      }
    });
  });

  group('过滤可用地址', () {
    test('保留 DNS 里能用的公网地址，丢弃真正的保留段地址', () {
      final filtered = filterPublicScriptAddresses(
        host: 'example.com',
        addresses: <InternetAddress>[
          InternetAddress('fe80::1'),
          InternetAddress('8.8.8.8'),
          InternetAddress('10.0.0.5'),
        ],
      );

      expect(
        filtered.map((address) => address.address).toList(),
        <String>['8.8.8.8'],
      );
    });

    test('全部为保留段地址时抛错并在消息里列出被拒地址', () {
      expect(
        () => filterPublicScriptAddresses(
          host: 'example.internal',
          addresses: <InternetAddress>[
            InternetAddress('10.0.0.1'),
            InternetAddress('192.168.1.1'),
          ],
        ),
        throwsA(
          isA<SafeScriptHttpException>().having(
            (exception) => exception.message,
            'message',
            allOf(
              contains('example.internal'),
              contains('10.0.0.1'),
              contains('192.168.1.1'),
            ),
          ),
        ),
      );
    });

    test('地址列表为空时抛出 host 未解析错误', () {
      expect(
        () => filterPublicScriptAddresses(
          host: 'unresolved.example',
          addresses: const <InternetAddress>[],
        ),
        throwsA(
          isA<SafeScriptHttpException>().having(
            (exception) => exception.message,
            'message',
            contains('unresolved.example'),
          ),
        ),
      );
    });
  });

  group('脚本 HTTP URI 校验', () {
    test('仅允许无用户信息的绝对 HTTP 与 HTTPS URI', () {
      expect(
        isValidScriptHttpUri(Uri.parse('https://example.com/video')),
        isTrue,
      );
      expect(
        isValidScriptHttpUri(Uri.parse('http://example.com/video')),
        isTrue,
      );
      expect(
        isValidScriptHttpUri(Uri.parse('https://user@example.com/video')),
        isFalse,
      );
      expect(isValidScriptHttpUri(Uri.parse('file:///private/video')), isFalse);
      expect(isValidScriptHttpUri(Uri.parse('/relative/video')), isFalse);
    });

    test('拒绝非白名单 HTTP 方法且不会发起网络解析', () async {
      final client = SafeScriptHttpClient();

      await expectLater(
        client.request(uri: Uri.parse('https://example.com'), method: 'TRACE'),
        throwsA(isA<SafeScriptHttpException>()),
      );
    });
  });

  group('脚本 HTTP 响应上限', () {
    test('接受不超过上限的分块响应', () async {
      final responseBytes = await collectScriptResponseBytes(
        Stream<List<int>>.fromIterable(<List<int>>[
          <int>[1, 2],
          <int>[3, 4],
        ]),
        declaredLength: 4,
        maximumBytes: 4,
      );

      expect(responseBytes, <int>[1, 2, 3, 4]);
    });

    test('在声明长度超过上限时立即拒绝', () async {
      await expectLater(
        collectScriptResponseBytes(
          const Stream<List<int>>.empty(),
          declaredLength: 5,
          maximumBytes: 4,
        ),
        throwsA(isA<SafeScriptHttpException>()),
      );
    });

    test('在实际流量超过上限时中止读取', () async {
      await expectLater(
        collectScriptResponseBytes(
          Stream<List<int>>.fromIterable(<List<int>>[
            <int>[1, 2, 3],
            <int>[4, 5],
          ]),
          maximumBytes: 4,
        ),
        throwsA(isA<SafeScriptHttpException>()),
      );
    });
  });
}
