import 'dart:convert';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:generp/Models/crmModels/crmLeadDetailsGenerateQuotationViewResponse.dart';
import 'package:generp/Models/crmModels/crmSelectedProductDetailsResponse.dart';
import 'package:generp/screens/LoginScreen.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../Utils/commonServices.dart';
import '../../services/api_calling.dart';
import '../HomeScreenNotifier.dart';

class Crmgeneratequotationprovider extends ChangeNotifier {
  final FlutterLocalNotificationsPlugin _notificationsPlugin =
      FlutterLocalNotificationsPlugin();
  static const platform = MethodChannel('in.webgrid.generp/download');

  final GlobalKey webViewKey = GlobalKey();
  var dl = DownloadManager();
  bool _buttonsLoading = false;
  ProductsData? _selectedProductsDeatilsData;
  TextEditingController addEditProductPriceController = TextEditingController();
  TextEditingController addEditQuantityController = TextEditingController();
  TextEditingController addEditTotalAmountController = TextEditingController();
  TextEditingController mailIdController = TextEditingController();
  TextEditingController mobileController = TextEditingController();
  TextEditingController subjectsController = TextEditingController();
  TextEditingController taxesController = TextEditingController();
  TextEditingController SpecialNoteController = TextEditingController();
  TextEditingController forController = TextEditingController();
  TextEditingController paymentTermsController = TextEditingController();
  List<Map<String, dynamic>> _productRows = []; // For backend

  List<Map<String, dynamic>> get productRows => _productRows;

  bool get buttonsLoading => _buttonsLoading;

  set buttonsLoading(bool value) {
    _buttonsLoading = value;
    notifyListeners();
  }

  set productRows(value) {
    _productRows = value;
    productRowsError = "";
    notifyListeners();
  }

  String? _selectedTaxes;

  String? mailIdError = "";
  String? mobileError = "";
  String? subjectsError = "";
  String? productRowsError = "";
  String? taxesError = "";
  String? SpecialNoteError = "";
  String? forError = "";
  String? paymentTermsError = "";

  QuoteDetails _quoteDetails = QuoteDetails();
  List<LeadProducts> _leadProductsList = [];
  List<Products> _productsList = [];
  bool _isLoading = true;
  String? _quotationFilePath;
  LeadProducts? _selectedLeadProducts;
  Products? _selectedProducts;

  String? _selectedAddEditLeadProductId;
  String? _selectedAddEditLeadProductName;
  String? _selectedAddEditProductName;
  String? _selectedAddEditProductId;
  List<TextEditingController> editProductPriceControllers = [];
  List<TextEditingController> editQuantityControllers = [];
  List<TextEditingController> editTotalAmountControllers = [];

  ProductsData? get selectedProductsDetailsData => _selectedProductsDeatilsData;

  String? get selectedTaxes => _selectedTaxes;

  final List<String?> _selectedProductIds = [];
  final List<String?> _selectedValues = [];
  bool _submitLoading = false;

  String? get quotationFilePath => _quotationFilePath;

  QuoteDetails get quoteDetails => _quoteDetails;

  List<LeadProducts> get leadProductsList => _leadProductsList;
  List<Products> get productsList => _productsList;

  set leadProductsList(List<LeadProducts> value) {
    _leadProductsList = value;
    notifyListeners();
  }

  set productsList(List<Products> value) {
    _productsList = value;
    notifyListeners();
  }

  set selectedTaxes(String? value) {
    _selectedTaxes = value;
    taxesError = "";
    notifyListeners();
  }

  LeadProducts? get selectedLeadProducts => _selectedLeadProducts;
  Products? get selectedProducts => _selectedProducts;

  bool get isLoading => _isLoading;

  List<String?> get selectedProductIds => _selectedProductIds;

  String? get selectedAddEditLeadProductId => _selectedAddEditLeadProductId;

  String? get selectedAddEditLeadProductName => _selectedAddEditLeadProductName;

  String? get selectedAddEditProductId => _selectedAddEditProductId;

  String? get selectedAddEditProductName => _selectedAddEditProductName;

  List<String?> get selectedValues => _selectedValues;

  bool get submitLoading => _submitLoading;

  set selectedLeadProducts(LeadProducts? value) {
    _selectedLeadProducts = value;
    _selectedAddEditLeadProductId = value?.productId!;
    _selectedAddEditLeadProductName = value?.productName;
    notifyListeners();
  }

  set selectedProducts(Products? value) {
    _selectedProducts = value;
    _selectedAddEditProductId = value!.id!;
    _selectedAddEditProductName = value.name;
    notifyListeners();
  }

  set selectedAddEditProductId(String? value) {
    _selectedAddEditProductId = value;
    notifyListeners();
  }

  set selectedAddEditProductName(String? value) {
    _selectedAddEditProductName = value;
    notifyListeners();
  }

  set selectedAddEditLeadProductId(String? value) {
    _selectedAddEditLeadProductId = value;
    notifyListeners();
  }

  set selectedAddEditLeadProductName(String? value) {
    _selectedAddEditLeadProductName = value;
    notifyListeners();
  }

  set submitLoading(bool value) {
    _submitLoading = value;
    notifyListeners();
  }

  void addEditUpdateTotalAmount(value) {
    final price = double.tryParse(addEditProductPriceController.text) ?? 0;
    final qty = int.tryParse(addEditQuantityController.text) ?? 0;
    addEditTotalAmountController.text = (price * qty).toString();
    notifyListeners();
  }

  void editProduct(int index, LeadProducts updatedProduct) {
    if (index >= 0 && index < leadProductsList.length) {
      leadProductsList[index] = updatedProduct;
      _productRows[index] = {
        "product_id": updatedProduct.productId,
        "price": updatedProduct.price,
        "qty": updatedProduct.qty,
        "net_price": updatedProduct.prodTotalPrice,
      };
      notifyListeners();
    }
  }

  void addEditInitializeForm(BuildContext context) {
    checkDropdownReset();
    addEditProductPriceController.clear();
    addEditQuantityController.clear();
    addEditTotalAmountController.clear();
    selectedLeadProducts = null;
    selectedAddEditLeadProductId = null;
    selectedAddEditLeadProductName = null;
    notifyListeners();
  }

  void preFillFormForEdit(LeadProducts product, int index) {
    final newprod = product;
    selectedProducts = productsList.firstWhere(
      (p) => p.id == newprod.productId,
      orElse: () => Products(id: '', name: 'Unknown'),
    );
    // selectedLeadProducts = product;

    selectedAddEditProductId = product.productId;
    selectedAddEditProductName = product.productName;

    addEditProductPriceController.text = product.price?.toString() ?? '';
    addEditQuantityController.text = product.qty?.toString() ?? '';
    addEditTotalAmountController.text =
        product.prodTotalPrice?.toString() ?? '';
    notifyListeners();
  }

  void initializeForm(BuildContext context) {
    // Clear existing controllers
    editProductPriceControllers.clear();
    editQuantityControllers.clear();
    editTotalAmountControllers.clear();
    _selectedProductIds.clear();
    _selectedValues.clear();

    // Initialize controllers for each lead product
    for (var product in _leadProductsList) {
      editProductPriceControllers.add(
        TextEditingController(text: product.price?.toString() ?? ''),
      );
      editQuantityControllers.add(
        TextEditingController(text: product.qty?.toString() ?? ''),
      );
      editTotalAmountControllers.add(
        TextEditingController(
          text:
              (double.parse(product.price?.toString() ?? '0') *
                      int.parse(product.qty?.toString() ?? '0'))
                  .toString(),
        ),
      );
      _selectedProductIds.add(product.productId);
      _selectedValues.add(product.productName);
    }

    // Add one empty row if the list is empty
    if (_leadProductsList.isEmpty) {
      editAddNewRow();
    }

    notifyListeners();
  }

  Future<void> crmSelectedProductDetailsApiFunction(
    BuildContext context,
    String productId,
  ) async {
    try {
      final prov = Provider.of<HomescreenNotifier>(context, listen: false);
      final data = await ApiCalling.crmSelectedProductDetailsApi(
        prov.empId,
        prov.session,
        productId,
      );

      if (data != null && data.error == "0") {
        _selectedProductsDeatilsData = data.productsData!;
        addEditProductPriceController.text = data.productsData!.price!;
        notifyListeners();
      }
    } catch (e, s) {
      print("Error: $e, Stack: $s");
    }
  }

  void editAddNewRow() {
    editProductPriceControllers.add(TextEditingController());
    editQuantityControllers.add(TextEditingController());
    editTotalAmountControllers.add(TextEditingController());
    _selectedProductIds.add(null);
    _selectedValues.add(null);
    notifyListeners();
  }

  void editRemoveRow(int index) {
    editProductPriceControllers[index].dispose();
    editQuantityControllers[index].dispose();
    editTotalAmountControllers[index].dispose();
    editProductPriceControllers.removeAt(index);
    editQuantityControllers.removeAt(index);
    editTotalAmountControllers.removeAt(index);
    _selectedProductIds.removeAt(index);
    _selectedValues.removeAt(index);
    notifyListeners();
  }

  void updateSelectedProductIds(int index, LeadProducts value) {
    _selectedProductIds[index] = value.id;
    _selectedValues[index] = value.productName;
    notifyListeners();
  }

  void updateTotalAmount(int index) {
    final price = double.tryParse(editProductPriceControllers[index].text) ?? 0;
    final qty = int.tryParse(editQuantityControllers[index].text) ?? 0;
    editTotalAmountControllers[index].text = (price * qty).toString();
    notifyListeners();
  }

  //[{"product_id":"32","price":"40000","qty":"1","net_price":"40000"},
  // {"product_id":"7","price":"318437.52","qty":"1","net_price":"318437.52"}]

  List<Map<String, String>> getFormData() {
    final List<Map<String, String>> insertData = [];
    for (int i = 0; i < editProductPriceControllers.length; i++) {
      if (_selectedProductIds[i] != null) {
        final rowData = {
          "product_id": _selectedProductIds[i]!,
          "price": editProductPriceControllers[i].text,
          "qty": editQuantityControllers[i].text,
          "net_price": editTotalAmountControllers[i].text,
        };
        insertData.add(rowData);
      }
    }
    return insertData;
  }

  Future<void> crmLeadDetailsGenerateQuoteViewAPIFunction(
    BuildContext context,
    String leadID,
  ) async {
    try {
      final prov = Provider.of<HomescreenNotifier>(context, listen: false);
      final data = await ApiCalling.crmLeadDetailsGenerateQuotationViewAPI(
        prov.empId,
        prov.session,
        leadID,
      );
      if (data != null) {
        if (data.sessionExists == 1) {
          if (data.error == "0") {
            _isLoading = false;
            _leadProductsList = data.leadProducts ?? [];
            _productsList = data.products ?? [];

            _quoteDetails =
                data.quoteDetails ??
                QuoteDetails(
                  accountId: "",
                  email: "",
                  forText: "",
                  mobile: "",
                  name: "",
                  paymentTerms: "",
                  subject: "",
                );
            mailIdController.text = data.quoteDetails!.email ?? "-";
            mobileController.text = data.quoteDetails!.mobile ?? "-";
            subjectsController.text = data.quoteDetails!.subject ?? "-";
            // taxesController.text = data.quoteDetails!1;
            // SpecialNoteController.text = data.quoteDetails;
            forController.text = data.quoteDetails!.forText ?? "-";
            paymentTermsController.text =
                data.quoteDetails!.paymentTerms ?? "-";

            for (var product in data.leadProducts!) {
              _productRows.add({
                "product_id": product.productId!,
                "price": product.price,
                "qty": product.qty,
                "net_price": product.prodTotalPrice,
              });
            }
            print("_productRows : $_productRows");
            notifyListeners();
          } else {
            _isLoading = false;
            notifyListeners();
          }
        } else {
          sessionDoesNotExist(context);
        }
      } else {
        _isLoading = false;
        notifyListeners();
      }
    } catch (e, s) {
      print("Error: $e, Stack: $s");
    }
  }

  Future<void> crmLeadDetailsGenerateQuoteSubmitAPIFunction(
    BuildContext context,
    String leadID,
    quoteProducts,
    quotationType,
  ) async {
    try {
      if (!validateform()) {
        return;
      }
      _buttonsLoading = true;
      notifyListeners();
      final prov = Provider.of<HomescreenNotifier>(context, listen: false);
      final data = await ApiCalling.crmLeadDetailsGenerateQuotationSubmitAPI(
        prov.empId,
        prov.session,
        leadID,
        mobileController.text,
        subjectsController.text,
        taxesController.text,
        SpecialNoteController.text,
        forController.text,
        paymentTermsController.text,
        mailIdController.text,
        quoteProducts,
        quotationType,
      );
      if (data != null) {
        if (data.error == "0") {
          _buttonsLoading = false;
          _quotationFilePath = data.quoteFilepath!;
          if (quotationType == "genquotedown") {
            String suggestedFilename = getUniqueFilename('quotation', 'pdf');
            String contentDisposition =
                'attachment; filename="$suggestedFilename"';
            // openWhatsApp(data.quoteFilepath!);
            _handleDownload(
              context,
              data.quoteFilepath!,
              contentDisposition,
              'application/octet-stream',
              '',
            );
          } else if (quotationType == "genquotewhatsappbymynum") {
            openWhatsApp(data.quoteFilepath!);
          }
          Navigator.pop(context, true);
          toast(context, data.message);
          resetForm();
          notifyListeners();
        } else {
          _buttonsLoading = false;
          notifyListeners();
        }
      } else {
        _buttonsLoading = false;
        notifyListeners();
      }
    } catch (e, s) {
      _buttonsLoading = false;
      notifyListeners();
      print("Error: $e, Stack: $s");
    }
  }

  String getUniqueFilename(String baseName, [String ext = 'pdf']) {
    final now = DateTime.now();
    final formattedDate = DateFormat('yyyyMMdd_HHmmss').format(now);
    return '${baseName}_$formattedDate.$ext';
  }

  void openWhatsApp(String path) async {
    final Uri url = Uri.parse(path); // Example: 919876543210
    if (await canLaunchUrl(url)) {
      await launchUrl(url, mode: LaunchMode.externalApplication);
    } else {
      throw 'Could not launch $url';
    }
  }

  Future<void> _handleDownload(
    context,
    String url,
    String contentDisposition,
    String mimeType,
    String suggestedFilename,
  ) async {
    // Request notification permission for Android 13+
    if (Platform.isIOS) {
      _handleIOSDownload(context, url, suggestedFilename);
    } else if (Platform.isAndroid) {
      if (await Permission.notification.request().isGranted) {
        try {
          // Show custom notification (optional, since DownloadManager shows its own)

          if (Platform.isAndroid) {
            // Call native Android Download Manager
            final userAgent = 'Flutter InAppWebView';
            await platform.invokeMethod('startDownload', {
              'url': url,
              'userAgent': userAgent,
              'contentDisposition': contentDisposition,
              'mimeType': mimeType,
              'suggestedFilename': suggestedFilename,
            });
            await launchUrl(
              Uri.parse(url),
              mode: LaunchMode.externalApplication,
            );
          } else if (Platform.isIOS) {
            _handleIOSDownload(context, url, suggestedFilename);
          }
        } catch (e) {
          print("Download Error $e");
        }
      } else {
        toast(context, "Notification Permission Denied");
      }
    }
  }

  Future<void> _handleIOSDownload(
    context,
    String url,
    String suggestedFilename,
  ) async {
    try {
      // Show initial download notification
      await _showDownloadNotification(0, suggestedFilename, isComplete: false);

      // Get the temporary directory for iOS
      final tempDir = await getTemporaryDirectory();
      final fileName =
          suggestedFilename.isNotEmpty
              ? suggestedFilename
              : url.split('/').last;
      final filePath = '${tempDir.path}/$fileName';

      // Download the file using http
      final response = await http.get(Uri.parse(url));
      if (response.statusCode == 200) {
        // Save the file
        final file = File(filePath);
        await file.writeAsBytes(response.bodyBytes);

        // Show completion notification
        await _showDownloadNotification(100, fileName, isComplete: true);

        // Optionally, open the file or notify the user
        toast(context, "File downloaded to $filePath");
      } else {
        throw Exception("Failed to download file: HTTP ${response.statusCode}");
      }
    } catch (e) {
      print("iOS Download Error: $e");
      await _showDownloadNotification(
        0,
        suggestedFilename,
        isComplete: false,
        isError: true,
      );
      toast(context, "Failed to download file: $e");
    }
  }

  Future<void> _showDownloadNotification(
    int progress,
    String fileName, {
    bool isComplete = false,
    bool isError = false,
  }) async {
    final androidDetails = AndroidNotificationDetails(
      'download_channel',
      'Downloads',
      channelDescription: 'Notifications for file downloads',
      importance: Importance.high,
      priority: Priority.high,
      showProgress: !isComplete && !isError,
      maxProgress: 100,
      progress: progress,
      ongoing: !isComplete && !isError,
      playSound: isComplete || isError,
      styleInformation: BigTextStyleInformation(
        isError
            ? 'Download failed for $fileName'
            : isComplete
            ? 'Download complete: $fileName'
            : 'Downloading $fileName...',
      ),
    );

    final iosDetails = DarwinNotificationDetails(
      presentAlert: true,
      presentBadge: true,
      presentSound: isComplete || isError,
      subtitle:
          isError
              ? 'Download failed'
              : isComplete
              ? 'Download complete'
              : 'Downloading...',
      threadIdentifier: 'download_thread',
    );

    final notificationDetails = NotificationDetails(
      android: androidDetails,
      iOS: iosDetails,
    );

    await _notificationsPlugin.show(
      fileName.hashCode, // Unique ID for the notification
      isError
          ? 'Download Failed'
          : isComplete
          ? 'Download Complete'
          : 'Downloading File',
      isError
          ? 'Failed to download $fileName'
          : isComplete
          ? 'Successfully downloaded $fileName'
          : 'Downloading $fileName ($progress%)',
      notificationDetails,
    );
  }

  onChangemailId(value) {
    mailIdError = "";
    notifyListeners();
  }

  onChangemobile(value) {
    mobileError = "";
    notifyListeners();
  }

  onChangesubjects(value) {
    subjectsError = "";
    notifyListeners();
  }

  onChangetaxes(value) {
    taxesError = "";
    notifyListeners();
  }

  onChangeSpecialNote(value) {
    SpecialNoteError = "";
    notifyListeners();
  }

  onChangefor(value) {
    forError = "";
    notifyListeners();
  }

  onChangepaymentTerms(value) {
    paymentTermsError = "";
    notifyListeners();
  }

  bool validateform() {
    bool isValid = true;
    if (mailIdController.text.trim().isEmpty) {
      mailIdError = "Please Enter Email ID";
      isValid = false;
    }
    if (mobileController.text.trim().isEmpty) {
      mobileError = "Please Enter Mobile Number";
      isValid = false;
    } else {
      if (mobileController.text.length < 10) {
        mobileError = "Mobile Number should be 10 digits";
        isValid = false;
      }
    }
    if (subjectsController.text.isEmpty) {
      subjectsError = "Please Enter Subject";
      isValid = false;
    }
    if (productRows.isEmpty || _productRows.isEmpty) {
      productRowsError = "Please Add Min. 1 Product";
      isValid = false;
    }
    if (_selectedTaxes == null || _selectedTaxes == "") {
      taxesError = "Please select a value";
      isValid = false;
    }
    if (SpecialNoteController.text.trim().isEmpty) {
      SpecialNoteError = "Please Enter a Note";
      isValid = false;
    }
    if (forController.text.trim().isEmpty) {
      forError = "Please Enter FOR";
      isValid = false;
    }
    if (paymentTermsController.text.trim().isEmpty) {
      paymentTermsError = "Please Enter Terms";
      isValid = false;
    }
    _buttonsLoading = false;
    notifyListeners();
    return isValid;
  }

  void resetForm() {
    checkDropdownReset();
    _productRows.clear();
    selectedTaxes = null;
    addEditProductPriceController.clear();
    addEditQuantityController.clear();
    addEditTotalAmountController.clear();
    editProductPriceControllers.clear();
    editQuantityControllers.clear();
    editTotalAmountControllers.clear();
    _selectedLeadProducts = null;
    _selectedAddEditLeadProductId = null;
    _selectedAddEditLeadProductName = null;
    _selectedAddEditProductName = null;
    _selectedAddEditProductId = null;
    _selectedProducts = null;
    notifyListeners();
  }

  void checkDropdownReset() {
    if (!_leadProductsList.contains(_selectedLeadProducts) &&
        _selectedLeadProducts != null) {
      _selectedAddEditLeadProductId = null;
      _selectedAddEditLeadProductName = null;
    }
    notifyListeners();
  }

  resetForm2() {
    _selectedAddEditProductName = null;
    _selectedAddEditProductId = null;
    _selectedProducts = null;
    mailIdController.clear();
    mobileController.clear();
    subjectsController.clear();
    taxesController.clear();
    SpecialNoteController.clear();
    forController.clear();
    paymentTermsController.clear();
    editProductPriceControllers.clear();
    editQuantityControllers.clear();
    editTotalAmountControllers.clear();
    _selectedProductIds.clear();
    _selectedValues.clear();
    _leadProductsList.clear();
    mailIdError = "";
    mobileError = "";
    subjectsError = "";
    productRowsError = "";
    taxesError = "";
    SpecialNoteError = "";
    forError = "";
    paymentTermsError = "";
    notifyListeners();
  }
}
