import 'dart:async';
import 'dart:convert';
import 'dart:math';

import 'package:lunchpick/domain/entities/restaurant.dart';
import 'package:lunchpick/domain/entities/share_device.dart';

/// 실제 Bluetooth 통신을 대체하는 간단한 모의(Mock) 서비스.
class BluetoothService {
  final _incomingDataController = StreamController<String>.broadcast();
  final Map<String, ShareDevice> _listeningDevices = {};
  final Random _random = Random();

  Stream<String> get onDataReceived => _incomingDataController.stream;

  /// 특정 코드로 수신 대기를 시작한다.
  Future<void> startListening(String code) async {
    await Future<void>.delayed(const Duration(milliseconds: 300));
    stopListening();
    final shareDevice = ShareDevice(
      code: code,
      deviceId: 'LP-${_random.nextInt(900000) + 100000}',
      discoveredAt: DateTime.now(),
    );
    _listeningDevices[code] = shareDevice;
  }

  /// 더 이상 수신 대기하지 않는다.
  void stopListening() {
    if (_listeningDevices.isEmpty) return;
    final codes = List<String>.from(_listeningDevices.keys);
    for (final code in codes) {
      _listeningDevices.remove(code);
    }
  }

  /// 현재 주변에서 수신 대기 중인 기기 목록을 반환한다.
  Future<List<ShareDevice>> scanNearbyDevices() async {
    await Future<void>.delayed(const Duration(seconds: 1));
    return _listeningDevices.values.toList();
  }

  /// 대상 코드로 맛집 리스트를 전송한다. 실제 BT 대신 JSON 문자열을 브로드캐스트한다.
  Future<void> sendRestaurantList(
    String targetCode,
    List<Restaurant> restaurants,
  ) async {
    await Future<void>.delayed(const Duration(seconds: 1));
    if (!_listeningDevices.containsKey(targetCode)) {
      throw Exception('해당 코드를 찾을 수 없습니다.');
    }

    final payload = jsonEncode(
      restaurants
          .map((restaurant) => _serializeRestaurant(restaurant))
          .toList(),
    );
    _incomingDataController.add(payload);
  }

  Map<String, dynamic> _serializeRestaurant(Restaurant restaurant) {
    return {
      'id': restaurant.id,
      'name': restaurant.name,
      'category': restaurant.category,
      'subCategory': restaurant.subCategory,
      'description': restaurant.description,
      'phoneNumber': restaurant.phoneNumber,
      'roadAddress': restaurant.roadAddress,
      'jibunAddress': restaurant.jibunAddress,
      'latitude': restaurant.latitude,
      'longitude': restaurant.longitude,
      'lastVisitDate': restaurant.lastVisitDate?.toIso8601String(),
      'source': restaurant.source.name,
      'createdAt': restaurant.createdAt.toIso8601String(),
      'updatedAt': restaurant.updatedAt.toIso8601String(),
      'naverPlaceId': restaurant.naverPlaceId,
      'naverUrl': restaurant.naverUrl,
      'businessHours': restaurant.businessHours,
      'lastVisited': restaurant.lastVisited?.toIso8601String(),
      'visitCount': restaurant.visitCount,
    };
  }

  void dispose() {
    _incomingDataController.close();
    _listeningDevices.clear();
  }
}
