import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart';
import 'package:http/io_client.dart';
import 'package:flutter/foundation.dart';

// Combined Deliverylog providers:

/// Hardcoded known-good IPs for hosts where carrier DNS returns broken CDN nodes.
/// Confirmed: 66.116.225.226 = 200 OK, 125.21.240.67 = 404/405.
const _knownGoodIPs = <String, String>{
  'queue.workolik.com': '66.116.225.226',
};

/// Creates an IOClient that:
/// 1. Bypasses SSL certificate errors
/// 2. Forces known-good IPs to avoid broken CDN nodes from carrier DNS
/// 3. Manually does TLS upgrade with correct SNI (hostname, not IP)
IOClient _buildSslBypassClient() {
  final httpClient = HttpClient()
    ..badCertificateCallback =
        (X509Certificate cert, String host, int port) => true;

  httpClient.connectionFactory =
      (Uri uri, String? proxyHost, int? proxyPort) async {
    final host = uri.host;
    final port = uri.port;

    InternetAddress? target;
    final knownIP = _knownGoodIPs[host];
    if (knownIP != null) {
      target = InternetAddress(knownIP);
    } else {
      try {
        final addresses = await InternetAddress.lookup(
          host,
          type: InternetAddressType.IPv4,
        );
        if (addresses.isNotEmpty) target = addresses.first;
      } catch (_) {}
    }

    if (uri.scheme == 'https') {
      final socketFuture =
          Socket.connect(target ?? InternetAddress(host), port)
              .then((plain) => SecureSocket.secure(
                    plain,
                    host: host,
                    onBadCertificate: (_) => true,
                    supportedProtocols: ['http/1.1'],
                  ))
              .then((s) => s as Socket);
      return ConnectionTask.fromSocket<Socket>(socketFuture, () {});
    }

    return Socket.startConnect(target ?? InternetAddress(host), port);
  };

  return IOClient(httpClient);
}

class CreateDeliveryLogProvider {
  Future<Map<String, dynamic>?> createDeliveryLog(
    String urldata,
    Map<String, dynamic> data, {
    bool wrapInArray = true,
  }) async {
    Map<String, dynamic>? result;
    final client = _buildSslBypassClient();
    try {
      final url = Uri.parse(urldata);
      final body = json.encode(wrapInArray ? [data] : data);
      final response = await client.post(
        url,
        body: body,
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
      ).timeout(const Duration(seconds: 10));
      debugPrint('createDeliveryLog url $urldata');
      debugPrint(body);
      debugPrint('createDeliveryLog response ${response.body}');
      if (response.statusCode >= 200 && response.statusCode < 300) {
        result = json.decode(response.body.toString()) as Map<String, dynamic>;
        debugPrint('createDeliveryLog parsed ${result.toString()}');
      } else {
        debugPrint('createDeliveryLog failed: HTTP ${response.statusCode}');
      }
    } on TimeoutException catch (e) {
      debugPrint('createDeliveryLog timeout: $e');
    } catch (e) {
      debugPrint('createDeliveryLog error: $e');
    } finally {
      client.close();
    }
    return result;
  }
}

class UpdateDeliveryProvider {
  Future<Map<String, dynamic>?> updateDelivery(
    Map<String, dynamic> data,
    String urldata,
  ) async {
    Map<String, dynamic>? updateDeliveryResponse;
    final client = _buildSslBypassClient();
    try {
      final url = Uri.parse(urldata);
      final response = await client.put(
        url,
        body: json.encode(data),
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
      ).timeout(const Duration(seconds: 10));
      debugPrint('updateDelivery url $urldata');
      debugPrint('updateDelivery status ${response.statusCode}');
      debugPrint('updateDelivery response ${response.body}');
      debugPrint(json.encode(data));
      if (response.statusCode >= 200 && response.statusCode < 300) {
        updateDeliveryResponse =
            json.decode(response.body) as Map<String, dynamic>;
      } else {
        debugPrint('updateDelivery failed: HTTP ${response.statusCode}');
      }
    } on TimeoutException catch (e) {
      debugPrint('updateDelivery timeout: $e');
    } catch (e) {
      debugPrint('updateDelivery error: $e');
    } finally {
      client.close();
    }
    return updateDeliveryResponse;
  }

  Future<Map<String, dynamic>?> updateArrivedDelivery(
    Map<String, dynamic> data,
    String urldata,
  ) async {
    Map<String, dynamic>? updateDeliveryResponse;
    final client = _buildSslBypassClient();
    try {
      final url = Uri.parse(urldata);
      final response = await client.put(
        url,
        body: json.encode(data),
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
      ).timeout(const Duration(seconds: 10));
      debugPrint('updateArrived url $urldata');
      debugPrint('updateArrived status ${response.statusCode}');
      debugPrint(json.encode(data));
      if (response.statusCode >= 200 && response.statusCode < 300) {
        updateDeliveryResponse =
            json.decode(response.body) as Map<String, dynamic>;
      } else {
        debugPrint('updateArrived failed: HTTP ${response.statusCode}');
      }
    } on TimeoutException catch (e) {
      debugPrint('updateArrived timeout: $e');
    } catch (e) {
      debugPrint('updateArrived error: $e');
    } finally {
      client.close();
    }
    return updateDeliveryResponse;
  }

  Future<Map<String, dynamic>?> updatePickedDelivery(
    Map<String, dynamic> data,
    String urldata,
  ) async {
    Map<String, dynamic>? updateDeliveryResponse;
    final client = _buildSslBypassClient();
    try {
      final url = Uri.parse(urldata);
      final response = await client.put(
        url,
        body: json.encode(data),
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
      ).timeout(const Duration(seconds: 10));
      debugPrint('updatePicked url $urldata');
      debugPrint('updatePicked status ${response.statusCode}');
      debugPrint(json.encode(data));
      if (response.statusCode >= 200 && response.statusCode < 300) {
        updateDeliveryResponse =
            json.decode(response.body) as Map<String, dynamic>;
      } else {
        debugPrint('updatePicked failed: HTTP ${response.statusCode}');
      }
    } on TimeoutException catch (e) {
      debugPrint('updatePicked timeout: $e');
    } catch (e) {
      debugPrint('updatePicked error: $e');
    } finally {
      client.close();
    }
    return updateDeliveryResponse;
  }

  Future<Map<String, dynamic>?> updateActiveDelivery(
    Map<String, dynamic> data,
    String urldata,
  ) async {
    Map<String, dynamic>? updateDeliveryResponse;
    final client = _buildSslBypassClient();
    try {
      final url = Uri.parse(urldata);
      final response = await client.put(
        url,
        body: json.encode(data),
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
      ).timeout(const Duration(seconds: 10));
      debugPrint('updateActive url $urldata');
      debugPrint('updateActive status ${response.statusCode}');
      debugPrint(json.encode(data));
      if (response.statusCode >= 200 && response.statusCode < 300) {
        updateDeliveryResponse =
            json.decode(response.body) as Map<String, dynamic>;
      } else {
        debugPrint('updateActive failed: HTTP ${response.statusCode}');
      }
    } on TimeoutException catch (e) {
      debugPrint('updateActive timeout: $e');
    } catch (e) {
      debugPrint('updateActive error: $e');
    } finally {
      client.close();
    }
    return updateDeliveryResponse;
  }
}

class GetDeliveryLogProvider {
  Future<Map<String, dynamic>?> getDeliveryLog(String urldata) async {
    Map<String, dynamic>? result;
    final client = _buildSslBypassClient();
    try {
      final url = Uri.parse(urldata);
      final response = await client.get(url, headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      });
      debugPrint('getDeliveryLog url $urldata');
      debugPrint('getDeliveryLog response ${response.body}');
      if (response.statusCode >= 200 && response.statusCode < 300) {
        result =
            json.decode(response.body.toString()) as Map<String, dynamic>;
      }
    } catch (e) {
      debugPrint('getDeliveryLog error: $e');
    } finally {
      client.close();
    }
    return result;
  }
}
