import 'dart:developer';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
import 'package:flutter_esc_pos_network/flutter_esc_pos_network.dart';
import 'package:print_bluetooth_thermal/print_bluetooth_thermal.dart';
import 'package:enaklo_pos/data/models/response/print_model.dart';
import 'package:synchronized/synchronized.dart';

class PrinterService {
  static final PrinterService _instance = PrinterService._internal();
  factory PrinterService() => _instance;
  PrinterService._internal();

  final Lock _lock = Lock();
  String? _connectedMac;

  /// Connect to Bluetooth printer
  Future<bool> connectBluetoothPrinter(String macAddress) async {
    try {
      // Check if already connected
      bool isConnected = await PrintBluetoothThermal.connectionStatus;
      if (isConnected) {
        log("Already connected to Bluetooth printer");
        return true;
      }

      // Connect to the printer
      bool connected =
          await PrintBluetoothThermal.connect(macPrinterAddress: macAddress);

      if (connected) {
        log("Successfully connected to Bluetooth printer: $macAddress");
      } else {
        FirebaseCrashlytics.instance.recordError(
          'Failed to connect to Bluetooth printer',
          null,
          reason: 'Failed to connect to Bluetooth printe',
          information: [
            'function: connectBluetoothPrinter(String macAddress)',
            'macAddress: $macAddress',
          ],
        );
        log("Failed to connect to Bluetooth printer: $macAddress");
      }

      return connected;
    } catch (e, stackTrace) {
      FirebaseCrashlytics.instance.recordError(
        e,
        stackTrace,
        reason: 'Error connecting to Bluetooth printer',
        information: [
          'function: connectBluetoothPrinter(String macAddress)',
          'Printer: Bluetooth printer',
          'macAddress: $macAddress',
        ],
      );
      log("Error connecting to Bluetooth printer: $e");
      return false;
    }
  }

  /// Print with automatic printer type detection
  Future<bool> printWithPrinter(
      PrintModel printer, List<int> printData, BuildContext context) async {
    if (printer.type == 'Bluetooth') {
      return await _lock.synchronized(() async {
        try {
          // Connect hanya kalau beda printer atau belum connected
          bool isConnected = await PrintBluetoothThermal.connectionStatus;
          if (!isConnected || _connectedMac != printer.address) {
            if (isConnected) {
              await PrintBluetoothThermal.disconnect;
              await Future.delayed(const Duration(milliseconds: 1500));
            }
            bool connected = await PrintBluetoothThermal.connect(
                macPrinterAddress: printer.address);
            if (!connected) {
              if (context.mounted) {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Gagal connect ke ${printer.name}')),
                );
              }
              return false;
            }
            _connectedMac = printer.address;
            await Future.delayed(const Duration(milliseconds: 500));
          }

          // Print
          bool result = await PrintBluetoothThermal.writeBytes(printData);
          log("Print result ${printer.name}: $result");
          return result;
        } catch (e, stackTrace) {
          _connectedMac = null;
          FirebaseCrashlytics.instance.recordError(
            e,
            stackTrace,
            reason: 'Error printing ${printer.name}',
            information: [
              'Printer: ${printer.name}',
              'MAC: ${printer.address}'
            ],
          );
          log("Error printing ${printer.name}: $e");
          return false;
        }
      });
    } else {
      return await printNetwork(printer, printData, context);
    }
  }

  /// Print using Bluetooth printer
  Future<bool> printBluetooth(List<int> printData) async {
    try {
      bool isConnected = await PrintBluetoothThermal.connectionStatus;
      if (!isConnected) {
        log("Not connected to Bluetooth printer");
        return false;
      }

      bool printResult = await PrintBluetoothThermal.writeBytes(printData);
      if (printResult) {
        log("Successfully printed via Bluetooth");
      } else {
        FirebaseCrashlytics.instance.recordError(
          'Failed to print via Bluetooth',
          null,
          reason: 'Failed to print via Bluetooth',
          information: [
            'function: printBluetooth(List<int> printData)',
            'printData: $printData',
          ],
        );
        log("Failed to print via Bluetooth");
      }

      return printResult;
    } catch (e, stackTrace) {
      FirebaseCrashlytics.instance.recordError(
        e,
        stackTrace,
        reason: 'Error printing via Bluetooth',
        information: [
          'function: printBluetooth(List<int> printData)',
          'Printer: Bluetooth printer',
          'printData: $printData',
        ],
      );
      log("Error printing via Bluetooth: $e");
      return false;
    }
  }

  /// Print using Network printer
  Future<bool> printNetwork(
      PrintModel printer, List<int> printData, BuildContext context) async {
    try {
      final networkPrinter = PrinterNetworkManager(printer.address);
      PosPrintResult connect = await networkPrinter.connect();

      if (connect == PosPrintResult.success) {
        PosPrintResult printing = await networkPrinter.printTicket(printData);
        networkPrinter.disconnect();

        if (printing == PosPrintResult.success) {
          log("Successfully printed via Network printer: ${printer.address}");
          return true;
        } else {
          FirebaseCrashlytics.instance.recordError(
            'Failed to print via Network printer: ${printing.msg}',
            null,
            reason: 'Failed to print via Network printer',
            information: [
              'Printer: ${printer.name}',
              'ipAddress: ${printer.address}',
            ],
          );
          log("Failed to print via Network printer: ${printing.msg}");
          if (context.mounted) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text('Gagal print ke ${printer.name}')),
            );
          }
          return false;
        }
      } else {
        FirebaseCrashlytics.instance.recordError(
          'Failed to connect to Network printer: ${connect.msg}',
          null,
          reason: 'Failed to connect Network printer',
          information: [
            'Printer: ${printer.name}',
            'ipAddress: ${printer.address}',
          ],
        );
        log("Failed to connect to Network printer: ${connect.msg}");
        if (context.mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Gagal connect ke ${printer.name}')),
          );
        }
        return false;
      }
    } catch (e, stackTrace) {
      FirebaseCrashlytics.instance.recordError(
        e,
        stackTrace,
        reason: 'Error printing via Network',
        information: [
          'Printer: ${printer.name}',
          'ipAddress: ${printer.address}',
        ],
      );
      log("Error printing via Network: $e");
      return false;
    }
  }

  /// Disconnect from Bluetooth printer
  Future<bool> disconnectBluetooth() async {
    try {
      bool result = await PrintBluetoothThermal.disconnect;
      log("Bluetooth printer disconnected: $result");
      return result;
    } catch (e) {
      log("Error disconnecting Bluetooth printer: $e");
      return false;
    }
  }

  /// Check if Bluetooth is enabled
  Future<bool> isBluetoothEnabled() async {
    try {
      return await PrintBluetoothThermal.bluetoothEnabled;
    } catch (e) {
      log("Error checking Bluetooth status: $e");
      return false;
    }
  }

  /// Get paired Bluetooth devices
  Future<List<BluetoothInfo>> getPairedBluetoothDevices() async {
    try {
      return await PrintBluetoothThermal.pairedBluetooths;
    } catch (e) {
      log("Error getting paired Bluetooth devices: $e");
      return [];
    }
  }
}
