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

import 'package:christian_period_tracker/models/scripture.dart';
import 'package:christian_period_tracker/models/user_profile.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
import 'package:mockito/mockito.dart';
import 'mocks.mocks.dart'; // Generated mock file

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  group('Scripture', () {
    test('fromJson creates a valid Scripture object', () {
      final json = {
        "verses": {
          "esv": "Test verse",
        },
        "reference": "Test 1:1",
      };
      final scripture = Scripture.fromJson(json);
      expect(scripture.reference, "Test 1:1");
      expect(scripture.getVerse(BibleTranslation.esv), "Test verse");
    });
  });

  group('ScriptureDatabase', () {
    late ScriptureDatabase database;
    late String testPath;

    setUpAll(() async {
      // Initialize path_provider_platform_interface for testing
      // This is a common pattern for mocking platform-specific plugins in tests.
      PathProviderPlatform.instance = _MockPathProviderPlatform();
      testPath = '${Directory.current.path}/test_hive_temp';

      // Ensure the directory exists
      final Directory tempDir = Directory(testPath);
      if (!await tempDir.exists()) {
        await tempDir.create(recursive: true);
      }

      // Create and configure the mock BibleXmlParser
      final mockBibleXmlParser = MockBibleXmlParser();
      when(mockBibleXmlParser.getVerseFromAsset(any, any))
          .thenAnswer((invocation) async {
        final String reference = invocation.positionalArguments[1];
        // Return a mock verse based on the reference for testing purposes
        return 'Mock Verse for $reference';
      });

      // Mock the rootBundle for JSON assets (XML assets are now handled by mockBibleXmlParser)
      TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
          .setMockMessageHandler(
        'flutter/assets',
        (ByteData? message) async {
          final String key = utf8.decode(message!.buffer.asUint8List());
          if (key == 'assets/scriptures.json' ||
              key == 'assets/scriptures_optimized.json') {
            final json = {
              "menstrual": [
                {
                  "verses": {"esv": "Menstrual verse"},
                  "reference": "Menstrual 1:1",
                  "applicablePhases": ["menstrual"]
                }
              ],
              "follicular": [
                {
                  "verses": {"esv": "Follicular verse"},
                  "reference": "Follicular 1:1",
                  "applicablePhases": ["follicular"]
                }
              ],
              "ovulation": [
                {
                  "verses": {"esv": "Ovulation verse"},
                  "reference": "Ovulation 1:1",
                  "applicablePhases": ["ovulation"]
                }
              ],
              "luteal": [
                {
                  "verses": {"esv": "Luteal verse"},
                  "reference": "Luteal 1:1",
                  "applicablePhases": ["luteal"]
                }
              ],
              "husband": [
                {
                  "verses": {"esv": "Husband verse"},
                  "reference": "Husband 1:1",
                  "applicablePhases": ["husband"]
                }
              ],
              "womanhood": [
                {
                  "verses": {"esv": "Womanhood verse"},
                  "reference": "Womanhood 1:1",
                  "applicableContexts": ["womanhood"]
                }
              ],
              "contextual": {
                "pain": [
                  {
                    "verses": {"esv": "Pain verse"},
                    "reference": "Pain 1:1",
                    "applicableContexts": ["pain"]
                  }
                ]
              }
            };
            return utf8.encode(jsonEncode(json)).buffer.asByteData();
          }
          return null; // Return null for other asset requests not explicitly mocked
        },
      );

      Hive.init(testPath);
      Hive.registerAdapter(ScriptureAdapter()); // Register your adapter
      Hive.registerAdapter(
          BibleTranslationAdapter()); // Register BibleTranslationAdapter
      database = ScriptureDatabase(
          bibleXmlParser: mockBibleXmlParser); // Instantiate with mock
      await database.loadScriptures();
    });

    tearDownAll(() async {
      await Hive.close();
      await Directory(testPath).delete(recursive: true);
    });

    test('getScriptureForPhase returns the correct scripture', () {
      final scripture = database.getScriptureForPhase('menstrual');
      expect(scripture.reference, "Menstrual 1:1");
    });

    test('getHusbandScripture returns a husband scripture', () {
      final scripture = database.getHusbandScripture();
      expect(scripture.applicablePhases, contains('husband'));
    });
  });
}

class _MockPathProviderPlatform extends PathProviderPlatform {
  @override
  Future<String?> getApplicationSupportPath() async {
    return '${Directory.current.path}/test_hive_temp';
  }

  @override
  Future<String?> getApplicationDocumentsPath() async {
    return '${Directory.current.path}/test_hive_temp';
  }
}
