import 'dart:convert';

import 'package:cipher_guard_sdk/src/data/constants/method_channel_constants.dart';
import 'package:flutter/services.dart';
import '../dto/method_channel_response.dart';

// ==================== Method Channel 資料來源 ====================

/// Method Channel 資料來源
/// 負責與原生平台 (iOS/Android) 通訊
///
/// 注意：加密邏輯移至 Flutter 端
/// 原生端僅保留同步功能
class EncryptionMethodChannelDataSource {
  final MethodChannel _channel;

  EncryptionMethodChannelDataSource() : _channel = const MethodChannel(EncryptionMethodChannel.channelName);

  // ==================== 內部響應解析 ====================

  /// 標準化響應解析
  /// 解析原生平台返回的標準化響應格式
  /// 格式: {"success": bool, "data": {...}, "error": String?}
  MethodChannelResponse<Map<String, dynamic>> _parseResponse(Object? result) {
    if (result == null) {
      return MethodChannelResponse.failure('Null response from native');
    }

    if (result is Map<String, dynamic>) {
      return _parseStandardResponse(result);
    }

    if (result is Map<Object?, Object?>) {
      var mapResult = _coerceToMapStringDynamic(result);
      return _parseStandardResponse(mapResult);
    }

    // 嘗試解析 JSON 字串
    if (result is String && result.startsWith('{')) {
      try {
        final decoded = jsonDecode(result);
        if (decoded is Map<String, dynamic>) {
          return _parseStandardResponse(decoded);
        }
      } catch (_) {}
    }

    // 不支援的格式
    return MethodChannelResponse.failure(
      'Unsupported response format: ${result.runtimeType}',
    );
  }

  /// 解析標準化響應格式
  MethodChannelResponse<Map<String, dynamic>> _parseStandardResponse(Map<String, dynamic> map) {
    final success = map['success'] == "true";
    final data = map['data'];
    final error = map['error'];
    final decodedResult = jsonDecode(data);
    if (success) {
      return MethodChannelResponse.success(decodedResult);
    }

    return MethodChannelResponse<Map<String, dynamic>>(
      isSuccess: success,
      data: null,
      error: error?.toString() ?? (success ? null : 'Unknown error'),
    );
  }

  /// 將任意回傳結果轉成 `Map<String, dynamic>`
  Map<String, dynamic> _coerceToMapStringDynamic(Object? result) {
    if (result == null) return <String, dynamic>{};

    if (result is Map) {
      return result.map((k, v) => MapEntry(k.toString(), v));
    }

    if (result is String) {
      try {
        final decoded = jsonDecode(result);
        if (decoded is Map) {
          return decoded.map((k, v) => MapEntry(k.toString(), v));
        }
      } catch (_) {}
    }

    return <String, dynamic>{};
  }

  // ==================== 原生平台同步 ====================

  /// 同步加密金鑰到原生平台
  Future<MethodChannelResponse<bool>> syncEncryptionKey({
    required String chatId,
    required int activeRound,
    required int round,
    required String activeKey,
    required bool isSingle,
  }) async {
    final result = await _channel.invokeMethod(
      EncryptionMethodChannel.syncEncryptionKey,
      {
        'chatId': chatId,
        'activeRound': activeRound,
        'round': round,
        'activeKey': activeKey,
        'isSingle': isSingle,
      },
    );

    final response = _parseResponse(result);
    return MethodChannelResponse<bool>(
      isSuccess: response.isSuccess,
      data: response.isSuccess,
      error: response.error,
    );
  }

  /// 批量同步所有加密金鑰
  Future<MethodChannelResponse<bool>> syncAllEncryptionKeys({
    required Map<String, Map<String, dynamic>> chatMap,
  }) async {
    final result = await _channel.invokeMethod(
      EncryptionMethodChannel.syncAllEncryptionKeys,
      {'chatMap': chatMap},
    );

    final response = _parseResponse(result);
    return MethodChannelResponse<bool>(
      isSuccess: response.isSuccess,
      data: response.isSuccess,
      error: response.error,
    );
  }

  // ==================== 配置相關 ====================

  /// 獲取平台版本
  Future<MethodChannelResponse<String>> getPlatformVersion() async {
    final result = await _channel.invokeMethod(
      EncryptionMethodChannel.getPlatformVersion,
    );

    final response = _parseResponse(result);
    if (response.isSuccess) {
      final version = response.data!['version']?.toString() ?? 'Unknown';
      return MethodChannelResponse.success(version);
    }
    return MethodChannelResponse.failure(response.error);
  }
}

