import 'dart:io';

import 'package:csv/csv.dart';
import 'package:excel/excel.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:generp/Models/financeModels/paymentRequisitionPaymentsDetailsResponse.dart';
import 'package:generp/Models/financeModels/paymentRequisitionPaymentsListResponse.dart';
import 'package:generp/Notifiers/HomeScreenNotifier.dart';
import 'package:generp/services/api_calling.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:permission_handler/permission_handler.dart';
import 'package:printing/printing.dart';
import 'package:provider/provider.dart';

import '../../Utils/commonServices.dart';

class Paymentrequisitionpaymentslistprovider extends ChangeNotifier{
  List<PaymentsList> _paymentsList = [];
  PaymentDetails _paymentDetails = PaymentDetails();
  List<String> _headings = [];
  List<String> _subHeadings = [];
  List<PaymentsList> get paymentsList => _paymentsList;
  PaymentDetails get paymentDetails => _paymentDetails;
  bool _isLoading = true;
  List<String> get Headings => _headings;
  List<String> get subHeadings => _subHeadings;
  bool get isLoading => _isLoading;

  Future<void> paymentsListAPI(context,from,to) async {
    try{
      var prov = Provider.of<HomescreenNotifier>(context,listen: false);
      _paymentsList.clear();
      _isLoading = true;
      notifyListeners();
      final data = await ApiCalling.paymentRequisitionPaymentListAPI(prov.empId, prov.session,from,to);
      if(data!=null){
        if(data.error=="0"){
          _isLoading = false;
          _paymentsList = data.paymentsList!;
          notifyListeners();
        }else if(data.error=="1"){
          _isLoading = false;
        }
        notifyListeners();
      }
    }catch(e,s){

    }
  }

  Future<void> paymentsListDetailsAPI(context,paymentId) async {
    try{
      var prov = Provider.of<HomescreenNotifier>(context,listen: false);
      final data = await ApiCalling.paymentRequisitionPaymentDetailsAPI(prov.empId, prov.session,paymentId);
      if(data!=null){
        if(data.error=="0"){
          _paymentDetails = data.paymentDetails??PaymentDetails(
            accountId: "-",
            accountName: "-",
            amount: "-",
            attachmentDirFilePath: "-",
            attachmentViewFileName: "-",
            createdDatetime: "-",
             description: "-",
             id: "-",
            updatedDatetime: "-",
            refType: "-",refId: "-",paymentRemarks: "-",paymentReferenceNumber: "-",paymentModeId: "-",paymentEmployeeName: "-",paymentDate: "-",paymentAccountName: "-",paymentAccountId: "-",mode: "-",isExists: "-",createdEmployeeId: "-",bankUpiId: "-",bankName: "-",bankIfscCode:"-",bankBranchName: "-",bankAccountNumber: "-",bankAccountHolderName:"-" ,
          );
          _headings = [
            "From Account",
            "Payment Mode",
            "Created Employee",
            "Attachment",
            "Payment Date",
            "Note",
            "Bank Name",
            "Bank Branch Name",
            "Bank IFSC Code",
            "Bank Holder Name",
            "Bank Account Number",
            "Bank UPI ID",
            "Payment Reference Number",
            "Created Date Time",
            "Updated Date Time"
          ];
          _subHeadings = [
            _paymentDetails.paymentAccountName??"-",
            _paymentDetails.mode??"-",
            _paymentDetails.paymentEmployeeName??"-",
            _paymentDetails.attachmentDirFilePath??"-",
            _paymentDetails.paymentDate??"-",
            _paymentDetails.paymentRemarks??"-",
            _paymentDetails.bankName??"-",
            _paymentDetails.bankBranchName??"-",
            _paymentDetails.bankIfscCode??"-",
            _paymentDetails.bankAccountHolderName??"-",
            _paymentDetails.bankAccountNumber??"-",
            _paymentDetails.bankUpiId??"-",
            _paymentDetails.paymentReferenceNumber??"-",
            _paymentDetails.createdDatetime??"-",
            _paymentDetails.updatedDatetime??"-"
          ];
          notifyListeners();
        }
      }
    }catch(e,s){

    }
  }

  List<List<String>> prepareExportData() {
    final headers = [
      'ID',
      'Payment Account',
      'Amount',
      'Branch',
      'Account Number',
      'Description',
      'Mode',
      'Payment Reference Number',
      'Created Employee',
      'Date',
    ];

    final rows =
    paymentsList
        .map(
          (item) =>
      [
        item.id ?? '',
        item.payAccount ?? '',
        item.amount ?? '',
        item.bankName??"",
        item.bankBranchName ?? '',
        item.bankAccountNumber ?? '',
        item.description ?? '',
        item.requestMode ?? '',
        item.paymentReferenceNumber ?? '',
        item.createdEmployee ?? '',
        item.createdDatetime ?? '',
      ],
    )
        .toList();

    return [headers, ...rows];
  }

  void copyToClipboard(BuildContext context) async {
    try {
      if (paymentsList.isEmpty) {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text("No data to copy")));
        return;
      }
      final data = prepareExportData();
      String raw = data.map((row) => row.join('\t')).join('\n');
      print('Clipboard data: $raw');
      await Clipboard.setData(ClipboardData(text: raw));
      toast(context, "Copied to Clipboard");
    } catch (e) {
      print('Error copying to clipboard: $e');
    }
  }

  Future<String> getSaveDirectory() async {
    // Try Downloads directory first
    try {
      if (Platform.isAndroid) {
        // Request storage permission for Android
        if (await Permission.storage
            .request()
            .isGranted ||
            await Permission.manageExternalStorage
                .request()
                .isGranted) {
          final dir = await getApplicationDocumentsDirectory();
          if (dir != null) {
            print('Using Downloads directory: ${dir.path}');
            return dir.path;
          }
        }
      }
    } catch (e) {
      print('Error accessing Downloads directory: $e');
    }

    // Fallback to shared Documents directory
    try {
      final dir = await getDownloadsDirectory();
      if (dir != null) {
        final customDir = Directory('${dir.path}/RequisitionData');
        if (!await customDir.exists()) {
          await customDir.create(recursive: true);
        }
        print('Using custom Documents directory: ${customDir.path}');
        return customDir.path;
      }
    } catch (e) {
      print('Error accessing Documents directory: $e');
    }

    // Final fallback to app's Documents directory
    final dir = await getApplicationDocumentsDirectory();
    print('Using app Documents directory: ${dir.path}');
    return dir.path;
  }

  Future<void> downloadCSV(BuildContext context) async {
    try {
      if (paymentsList.isEmpty) {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text("No data to export")));
        return;
      }
      final data = prepareExportData();
      final csvData = const ListToCsvConverter().convert(data);
      final dirPath = await getSaveDirectory();
      final file = File('$dirPath/requisition_data.csv');
      await file.writeAsString(csvData);
      print('CSV saved at: ${file.path}');
      bool exists = await file.exists();
      print('File exists: $exists');
      // await OpenFile.open(file.path); // Open the file
      // await Share.share(file.path); // Share the file
      toast(context, "CSV Downloaded");
    } catch (e) {
      print('Error downloading CSV: $e');
    }
  }

  Future<void> downloadXLS(BuildContext context) async {
    try {
      if (paymentsList.isEmpty) {
        toast(context, "No Data to export");
        return;
      }
      final data = prepareExportData();
      var excel = Excel.createExcel();
      Sheet sheet = excel['Sheet1'];
      for (var row in data) {
        sheet.appendRow(row.map((cell) => TextCellValue(cell)).toList());
      }
      final dirPath = await getSaveDirectory();
      final file = File('$dirPath/requisition_data.xlsx');
      final bytes = excel.encode();
      if (bytes == null) throw Exception("Excel encoding failed");
      await file.writeAsBytes(bytes);
      print('XLSX saved at: ${file.path}');
      bool exists = await file.exists();
      print('File exists: $exists');
      // await OpenFile.open(file.path); // Open the file
      // await Share.share([file.path], text: 'Requisition Data XLSX'); // Share the file
      toast(context, ("XLSX Downloaded and opened"));
    } catch (e) {
      print('Error downloading XLSX: $e');
    }
  }

  Future<void> downloadPDF(BuildContext context) async {
    try {
      if (paymentsList.isEmpty) {
        toast(context, "No Data to export");
        return;
      }
      final data = prepareExportData();
      final pdf = pw.Document();
      pdf.addPage(
        pw.Page(build: (context) => pw.Table.fromTextArray(data: data)),
      );
      final dirPath = await getSaveDirectory();
      final file = File('$dirPath/requisition_data.pdf');
      await file.writeAsBytes(await pdf.save());
      print('PDF saved at: ${file.path}');
      bool exists = await file.exists();
      print('File exists: $exists');
      // await OpenFile.open(file.path); // Open the file
      // await Share.shareXFiles([file.path], text: 'Requisition Data PDF'); // Share the file
      toast(context, "PDF Downloaded ");
    } catch (e) {
      print('Error downloading PDF: $e');
    }
  }

  Future<void> printData(BuildContext context) async {
    try {
      if (paymentsList.isEmpty) {
        toast(context, "No Data to Print");
        return;
      }
      final data = prepareExportData();
      final pdf = pw.Document();
      pdf.addPage(
        pw.Page(build: (context) => pw.Table.fromTextArray(data: data)),
      );
      await Printing.layoutPdf(
        onLayout: (PdfPageFormat format) async => pdf.save(),
      );
    } catch (e) {
      print('Error printing data: $e');
    }
  }

  void resetForm() {
    _paymentsList = [];
    _paymentDetails = PaymentDetails();
    _headings = [];
    _subHeadings = [];
  }
}