import 'package:flutter_test/flutter_test.dart';

import 'package:mini_tias/services/raw_capture_service.dart';

void main() {
  group('QuantitativeCaptureResult.fromMap', () {
    test('最小限のマップから正しくインスタンス化できる', () {
      final map = <dynamic, dynamic>{
        'dngPath': '/storage/emulated/0/Pictures/MiniTIAS/test.dng',
        'dngFileSize': 16000000,
        'metadata': <dynamic, dynamic>{},
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.dngPath, '/storage/emulated/0/Pictures/MiniTIAS/test.dng');
      expect(result.dngFileSize, 16000000);
      expect(result.metadata, isEmpty);
      expect(result.lscMap, isNull);
      expect(result.lscMapRowCount, isNull);
      expect(result.lscMapColumnCount, isNull);
    });

    test('dngFileSize が int として渡された場合でも正しく変換される', () {
      final map = <dynamic, dynamic>{
        'dngPath': '/test.dng',
        'dngFileSize': 12345678, // Dart の int
        'metadata': <dynamic, dynamic>{},
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.dngFileSize, 12345678);
      expect(result.dngFileSize, isA<int>());
    });

    test('dngFileSize が long 経由の num として渡された場合でも正しく int 変換される', () {
      // Kotlin の Long は Dart で num として渡される
      final map = <dynamic, dynamic>{
        'dngPath': '/test.dng',
        'dngFileSize': 16777216.0, // num (double として渡される場合)
        'metadata': <dynamic, dynamic>{},
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.dngFileSize, 16777216);
      expect(result.dngFileSize, isA<int>());
    });

    test('metadata がネスト構造を含む場合，全階層が Map<String, dynamic> 型になる', () {
      final map = <dynamic, dynamic>{
        'dngPath': '/test.dng',
        'dngFileSize': 100,
        'metadata': <dynamic, dynamic>{
          'settings': <dynamic, dynamic>{
            'exposure_time_ns': 10000000,
            'iso': 400,
          },
          'actual': <dynamic, dynamic>{'frame_duration_ns': 33333333},
        },
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.metadata, isA<Map<String, dynamic>>());
      expect(result.metadata['settings'], isA<Map<String, dynamic>>());
      expect(result.metadata['actual'], isA<Map<String, dynamic>>());
      final settings = result.metadata['settings'] as Map<String, dynamic>;
      expect(settings['exposure_time_ns'], 10000000);
      expect(settings['iso'], 400);
    });

    test('metadata 内のリスト要素も再帰変換される', () {
      final map = <dynamic, dynamic>{
        'dngPath': '/test.dng',
        'dngFileSize': 100,
        'metadata': <dynamic, dynamic>{
          'colorMatrix': <dynamic>[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
          'nested': <dynamic, dynamic>{
            'tags': <dynamic>['tag1', 'tag2'],
          },
        },
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.metadata['colorMatrix'], isA<List<dynamic>>());
      final nested = result.metadata['nested'] as Map<String, dynamic>;
      expect(nested['tags'], isA<List<dynamic>>());
    });

    test('lscMap が null の場合，フィールド lscMap も null になる', () {
      final map = <dynamic, dynamic>{
        'dngPath': '/test.dng',
        'dngFileSize': 100,
        'metadata': <dynamic, dynamic>{},
        'lscMap': null,
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.lscMap, isNull);
    });

    test('lscMap が List<List<double>> (List<dynamic> 経由) の場合，正しく変換される', () {
      final map = <dynamic, dynamic>{
        'dngPath': '/test.dng',
        'dngFileSize': 100,
        'metadata': <dynamic, dynamic>{},
        'lscMap': <dynamic>[
          <dynamic>[1.1, 1.2, 1.3],
          <dynamic>[1.4, 1.5, 1.6],
        ],
        'lscMapRowCount': 2,
        'lscMapColumnCount': 3,
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.lscMap, isNotNull);
      expect(result.lscMap, hasLength(2));
      expect(result.lscMap![0], hasLength(3));
      expect(result.lscMap![0][0], closeTo(1.1, 0.0001));
      expect(result.lscMap![1][2], closeTo(1.6, 0.0001));
      expect(result.lscMapRowCount, 2);
      expect(result.lscMapColumnCount, 3);
    });

    test('lscMap に Float (num) の値が含まれる場合でも double に正しくキャストされる', () {
      // Kotlin の Float は Dart で num 経由で渡される
      final map = <dynamic, dynamic>{
        'dngPath': '/test.dng',
        'dngFileSize': 100,
        'metadata': <dynamic, dynamic>{},
        'lscMap': <dynamic>[
          <dynamic>[
            1.0, // double
            2, // int も num として変換される
            3.14, // 精度のある double
          ],
        ],
        'lscMapRowCount': 1,
        'lscMapColumnCount': 3,
      };
      final result = QuantitativeCaptureResult.fromMap(map);
      expect(result.lscMap, isNotNull);
      final row = result.lscMap![0];
      expect(row[0], isA<double>());
      expect(row[1], isA<double>());
      expect(row[2], isA<double>());
      expect(row[1], closeTo(2.0, 0.0001));
      expect(row[2], closeTo(3.14, 0.0001));
    });
  });
}
