/*
 * Copyright (c) 2025
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

import 'package:flutter_test/flutter_test.dart';
import 'package:splash_video/splash_video.dart';

void main() {
  group('SplashVideoException', () {
    test('creates with message', () {
      const exception = SplashVideoException(message: 'Test error');
      expect(exception.message, equals('Test error'));
    });

    test('toString includes message', () {
      const exception = SplashVideoException(message: 'Test error');
      expect(exception.toString(), contains('Test error'));
      expect(exception.toString(), contains('SplashVideoException'));
    });

    test('can be caught as Exception', () {
      expect(
        () => throw const SplashVideoException(message: 'Error'),
        throwsA(isA<Exception>()),
      );
    });
  });

  group('FirstWhereOrNullExtension', () {
    test('returns first matching element', () {
      final list = [1, 2, 3, 4, 5];
      final result = list.firstWhereOrNull((e) => e > 3);
      expect(result, equals(4));
    });

    test('returns null when no match found', () {
      final list = [1, 2, 3, 4, 5];
      final result = list.firstWhereOrNull((e) => e > 10);
      expect(result, isNull);
    });

    test('returns first element for always-true predicate', () {
      final list = [1, 2, 3, 4, 5];
      final result = list.firstWhereOrNull((e) => true);
      expect(result, equals(1));
    });

    test('returns null for empty list', () {
      final list = <int>[];
      final result = list.firstWhereOrNull((e) => true);
      expect(result, isNull);
    });

    test('works with complex types', () {
      final list = [
        {'name': 'Alice', 'age': 30},
        {'name': 'Bob', 'age': 25},
        {'name': 'Charlie', 'age': 35},
      ];

      final result = list.firstWhereOrNull((e) => (e['age'] as int) > 30);
      expect(result, equals({'name': 'Charlie', 'age': 35}));
    });
  });

  group('Callback typedefs', () {
    test('OnSplashDuration can be invoked', () {
      Duration? capturedDuration;
      void callback(Duration duration) {
        capturedDuration = duration;
      }

      const testDuration = Duration(seconds: 5);
      callback(testDuration);

      expect(capturedDuration, equals(testDuration));
    });

    test('WarningCallback can be invoked', () {
      String? capturedWarning;
      void callback(String warning) {
        capturedWarning = warning;
      }

      const testWarning = 'Test warning message';
      callback(testWarning);

      expect(capturedWarning, equals(testWarning));
    });

    test('OnVideoError can be invoked', () {
      String? capturedError;
      void callback(String error) {
        capturedError = error;
      }

      const testError = 'Video load failed';
      callback(testError);

      expect(capturedError, equals(testError));
    });
  });
}
