import 'dart:io';

import 'package:flutter_test/flutter_test.dart';
import 'package:hive/hive.dart';
import 'package:lunchpick/data/repositories/restaurant_repository_impl.dart';
import 'package:lunchpick/data/datasources/remote/naver_search_service.dart';
import 'package:lunchpick/domain/entities/restaurant.dart';
import 'package:mocktail/mocktail.dart';

class _MockNaverSearchService extends Mock implements NaverSearchService {}

void main() {
  late Directory tempDir;
  late RestaurantRepositoryImpl repository;
  late _MockNaverSearchService mockSearchService;

  setUpAll(() {
    TestWidgetsFlutterBinding.ensureInitialized();
    if (!Hive.isAdapterRegistered(0)) {
      Hive.registerAdapter(RestaurantAdapter());
    }
    if (!Hive.isAdapterRegistered(1)) {
      Hive.registerAdapter(DataSourceAdapter());
    }
  });

  setUp(() async {
    tempDir = await Directory.systemTemp.createTemp('hive_restaurant_test');
    Hive.init(tempDir.path);
    mockSearchService = _MockNaverSearchService();
    repository = RestaurantRepositoryImpl(
      naverSearchService: mockSearchService,
    );
  });

  tearDown(() async {
    await Hive.deleteBoxFromDisk('restaurants');
    Hive.close();
    await tempDir.delete(recursive: true);
  });

  Restaurant buildDummyRestaurant({String id = 'r1'}) {
    return Restaurant(
      id: id,
      name: 'Test Place $id',
      category: 'korean',
      subCategory: 'bbq',
      description: 'great food',
      phoneNumber: '010-0000-0000',
      roadAddress: '서울시 중구 세종대로 110',
      jibunAddress: '서울시 중구 태평로1가 31',
      latitude: 37.5665,
      longitude: 126.9780,
      lastVisitDate: null,
      source: DataSource.USER_INPUT,
      createdAt: DateTime.now(),
      updatedAt: DateTime.now(),
      naverPlaceId: '123',
      naverUrl: 'https://map.naver.com/p/restaurant/123',
      businessHours: '00:00-24:00',
      lastVisited: null,
      visitCount: 0,
    );
  }

  test('add/get/update/delete works with Hive storage', () async {
    final restaurant = buildDummyRestaurant();

    await repository.addRestaurant(restaurant);
    final fetched = await repository.getRestaurantById(restaurant.id);
    expect(fetched?.name, restaurant.name);

    final updated = restaurant.copyWith(name: 'Updated');
    await repository.updateRestaurant(updated);
    final fetchedUpdated = await repository.getRestaurantById(restaurant.id);
    expect(fetchedUpdated?.name, 'Updated');

    await repository.deleteRestaurant(restaurant.id);
    final deleted = await repository.getRestaurantById(restaurant.id);
    expect(deleted, isNull);
  });

  test('addRestaurantFromUrl persists parsed restaurant', () async {
    final restaurant = buildDummyRestaurant(id: 'r2');
    when(
      () => mockSearchService.getRestaurantFromUrl(any()),
    ).thenAnswer((_) async => restaurant);

    final result = await repository.addRestaurantFromUrl(
      'https://map.naver.com/p/123',
    );

    expect(result.id, restaurant.id);
    final stored = await repository.getRestaurantById(restaurant.id);
    expect(stored, isNotNull);
    verify(() => mockSearchService.getRestaurantFromUrl(any())).called(1);
  });

  test('previewRestaurantFromUrl does not persist', () async {
    final restaurant = buildDummyRestaurant(id: 'preview');
    when(
      () => mockSearchService.getRestaurantFromUrl(any()),
    ).thenAnswer((_) async => restaurant);

    final preview = await repository.previewRestaurantFromUrl(
      'https://naver.me/abc',
    );

    expect(preview.id, restaurant.id);
    final stored = await repository.getRestaurantById(restaurant.id);
    expect(stored, isNull);
  });
}
