import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:generp/Utils/commonServices.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_download_manager/flutter_download_manager.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:generp/Utils/app_colors.dart';
import 'package:generp/Utils/commonWidgets.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:math';

import 'package:flutter/widgets.dart';
import 'package:url_launcher/url_launcher.dart';

// const MAX_PROGRESS = 100;

Future runErpScreenApp() async {
  await FlutterDownloader.initialize(
    debug: true, // optional: set false to disable printing logs to console
  );
  await Permission.storage.request();
}

class WebErpScreen extends StatefulWidget {
  final String erp_url;
  const WebErpScreen({super.key, required this.erp_url});

  @override
  State<WebErpScreen> createState() => _WebErpScreenState();
}

class _WebErpScreenState extends State<WebErpScreen> {
  final Completer<InAppWebViewController> _controller =
      Completer<InAppWebViewController>();
  var empId = "";
  var sessionId = "";
  bool isLoading = true;
  InAppWebViewController? _webViewController;
  PullToRefreshController? pullToRefreshController;
  PullToRefreshSettings pullToRefreshSettings = PullToRefreshSettings(
    color: AppColors.app_blue,
  );
  bool pullToRefreshEnabled = true;
  final FlutterLocalNotificationsPlugin _notificationsPlugin =
      FlutterLocalNotificationsPlugin();
  static const platform = MethodChannel('in.webgrid.generp/download');

  final GlobalKey webViewKey = GlobalKey();
  var dl = DownloadManager();
  @override
  void initState() {
    //  loadData();
    super.initState();
    pullToRefreshController =
        kIsWeb
            ? null
            : PullToRefreshController(
              settings: pullToRefreshSettings,
              onRefresh: () async {
                if (defaultTargetPlatform == TargetPlatform.android) {
                  _webViewController?.reload();
                } else if (defaultTargetPlatform == TargetPlatform.iOS) {
                  _webViewController?.loadUrl(
                    urlRequest: URLRequest(
                      url: await _webViewController?.getUrl(),
                    ),
                  );
                }
              },
            );
    // print("URL:${widget.url}");
    _initializeNotifications();
  }

  Future<void> _initializeNotifications() async {
    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');
    final InitializationSettings initializationSettings =
        InitializationSettings(android: initializationSettingsAndroid);
    await _notificationsPlugin.initialize(initializationSettings);

    // Create a notification channel for Android
    const AndroidNotificationChannel channel = AndroidNotificationChannel(
      'download_channel',
      'Downloads',
      description: 'Notifications for file downloads',
      importance: Importance.high,
    );
    await _notificationsPlugin
        .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin
        >()
        ?.createNotificationChannel(channel);
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        if (await _webViewController!.canGoBack()) {
          _webViewController!.goBack();
          return false; // Prevent default back button behavior
        }
        return true; // Allow default back button behavior
      },
      child: Scaffold(
        resizeToAvoidBottomInset: true,
        appBar: appbar(context, "Web ERP"),
        body: SafeArea(
          child: Container(
            child: Column(
              children: <Widget>[
                Expanded(
                  child: Stack(
                    children: [
                      InAppWebView(
                        initialUrlRequest: URLRequest(
                          url: WebUri(widget.erp_url),
                          allowsCellularAccess: true,
                          allowsConstrainedNetworkAccess: true,
                          allowsExpensiveNetworkAccess: true,
                        ),
                        androidOnGeolocationPermissionsShowPrompt: (
                          InAppWebViewController controller,
                          String origin,
                        ) async {
                          return GeolocationPermissionShowPromptResponse(
                            origin: origin,
                            allow: true,
                            retain: true,
                          );
                        },
                        initialOptions: InAppWebViewGroupOptions(
                          android: AndroidInAppWebViewOptions(
                            useWideViewPort: true,
                            loadWithOverviewMode: true,
                            allowContentAccess: true,
                            geolocationEnabled: true,
                            allowFileAccess: true,
                            databaseEnabled: true, // Enables the WebView database
                            domStorageEnabled: true, // Enables DOM storage
                            builtInZoomControls:
                                true, // Enables the built-in zoom controls
                            displayZoomControls:
                                false, // Disables displaying zoom controls
                            safeBrowsingEnabled: true, // Enables Safe Browsing
                            clearSessionCache: true,
                            loadsImagesAutomatically: true,
                            thirdPartyCookiesEnabled: true,
                            blockNetworkImage: false,
                            supportMultipleWindows: true,
                            blockNetworkLoads: false,
                            networkAvailable: true,
                              useShouldInterceptRequest:true,
                              hardwareAcceleration: true
          
          
                            // Enable camera access
                          ),
                          ios: IOSInAppWebViewOptions(
                            allowsInlineMediaPlayback: true,
                            allowsLinkPreview: true,
                            allowsBackForwardNavigationGestures: true,
                          ),
                          crossPlatform: InAppWebViewOptions(
                            javaScriptEnabled: true,
                            useOnDownloadStart: true,
                            allowFileAccessFromFileURLs: true,
                            allowUniversalAccessFromFileURLs: true,
                            mediaPlaybackRequiresUserGesture: true,
                          ),
                        ),
          
                        androidOnPermissionRequest: (
                          InAppWebViewController controller,
                          String origin,
                          List<String> resources,
                        ) async {
                          return PermissionRequestResponse(
                            resources: resources,
                            action: PermissionRequestResponseAction.GRANT,
                          );
                        },
                        onPermissionRequest: (controller, request) async {
                          return PermissionResponse(
                            resources: request.resources,
                            action: PermissionResponseAction.GRANT,
                          );
                        },
                        keepAlive: InAppWebViewKeepAlive(),
                        onWebViewCreated: (controller) {
                          _webViewController = controller;
                          _controller.complete(controller);
                          _webViewController!.addJavaScriptHandler(
                            handlerName: 'MobileAppJavascriptInterface',
                            callback: (args) {
                              print(
                                "JavaScript called MobileAppJavascriptInterface with args: $args",
                              );
                              return {'status': 'success'};
                            },
                          );
                          _webViewController!.addJavaScriptHandler(
                            handlerName: 'downloadFile',
                            callback: (args) async {
                              if (Platform.isAndroid) {
                                final url = args[0] as String;
                                await _handleDownload(
                                  url,
                                  '',
                                  'application/octet-stream',
                                  '',
                                );
                              }
                            },
                          );
                        },
                        pullToRefreshController: pullToRefreshController,
                        onLoadStart: (controller, url) {
                          return setState(() {
                            isLoading = true;
                          });
                        },
                        initialSettings: InAppWebViewSettings(
                          allowUniversalAccessFromFileURLs: true,
                          allowFileAccessFromFileURLs: true,
                          allowFileAccess: true,
                          allowsInlineMediaPlayback: true,
                          allowsPictureInPictureMediaPlayback: true,
                          allowsBackForwardNavigationGestures: true,
                          iframeAllow: "camera;microphone;files;media;",
                          domStorageEnabled: true,
                          allowContentAccess: true,
                          javaScriptEnabled: true,
                          supportZoom: true,
                          builtInZoomControls: true,
                          displayZoomControls: false,
                          textZoom: 125,
                          blockNetworkImage: false,
                          loadsImagesAutomatically: true,
                          safeBrowsingEnabled: true,
                          useWideViewPort: true,
                          loadWithOverviewMode: true,
                          javaScriptCanOpenWindowsAutomatically: true,
                          mediaPlaybackRequiresUserGesture: false,
                          geolocationEnabled: true,
                          useOnDownloadStart: true,
                          allowsLinkPreview: true,
                          databaseEnabled: true, // Enables the WebView database
                          clearSessionCache: true,
                          mediaType: "image/*,application/pdf",
                            useShouldInterceptRequest:true,
                          hardwareAcceleration: true
                        ),
                        shouldInterceptRequest: (controller, request) async {
                          final url = request.url.toString();
                          print('Intercepting request: $url, Headers: ${request.headers}');
                          if (url.endsWith('.pdf')) {
                            final response = await http.get(Uri.parse(url), headers: {
                              'Accept': 'application/pdf',
                            });
                            if (response.statusCode == 200 && response.headers['content-type']?.contains('application/pdf') == true) {
                              return WebResourceResponse(
                                contentType: 'application/pdf',
                                data: response.bodyBytes,
                              );
                            } else {
                              print('Failed to load PDF: Status ${response.statusCode}, Content-Type: ${response.headers['content-type']}');
                            }
                          }
                          return null;
                        },
                        shouldOverrideUrlLoading: (
                          controller,
                          navigationAction,
                        ) async {
                          var uri = navigationAction.request.url!;
                          print("urib scgefes");
                          print(uri);
                          print(uri.scheme);
                          if (uri.toString().contains('file_viewer_n  ame.php') && uri.toString().contains('.pdf')) {
                            final pdfPath = Uri.parse(uri.toString()).queryParameters['file_path'];
                            if (pdfPath != null) {
                              final pdfUrl = 'https://erp.gengroup.in/$pdfPath';
                              await controller.loadUrl(urlRequest: URLRequest(url: WebUri(pdfUrl)));
                              return NavigationActionPolicy.CANCEL;
                            }
                          }
                          if (uri.scheme == "tel") {
                            // Launch the phone dialer app with the specified phone number
                            if (await canLaunch(uri.toString())) {
                              await launch(uri.toString());
                              return NavigationActionPolicy.CANCEL;
                            }
                          } else if (uri.scheme == "mailto") {
                            if (await canLaunch(uri.toString())) {
                              await launch(uri.toString());
                              return NavigationActionPolicy.CANCEL;
                            }
                          } else if (uri.scheme == "whatsapp") {
                            // Launch WhatsApp with the specified chat or phone number
                            if (await canLaunch(uri.toString())) {
                              await launch(uri.toString());
                              return NavigationActionPolicy.CANCEL;
                            }
                          }
                          // // Check if the URL is trying to access the camera for image upload
                          // if (uri.scheme == 'camera' && uri.path.contains('/camera/')) {
                          //   // Handle camera image upload here
                          //   // You might want to display a custom UI for image selection or directly trigger the camera
                          //   // You can use platform-specific plugins like image_picker for this purpose
                          //   // Once the image is selected, you can pass it to the web view using JavaScript injection
                          //   if (await canLaunch(uri.toString())) {
                          //     await launch(uri.toString());
                          //     return NavigationActionPolicy.CANCEL;
                          //   }
                          // }
                          return NavigationActionPolicy.ALLOW;
                        },
          
                        onLoadStop: (controller, url) async {
                          if (url.toString().contains('file_viewer_name.php') && url.toString().contains('.pdf')) {
                            final uri = Uri.parse(url.toString());
                            final pdfPath = uri.queryParameters['file_path'];
                            if (pdfPath != null) {
                              final pdfUrl = 'https://erp.gengroup.in/$pdfPath';
                              await controller.evaluateJavascript(source: '''
            var pdfjsLib = window.pdfjsLib || document.createElement('script');
            pdfjsLib.src = 'https://mozilla.github.io/pdf.js/build/pdf.js';
            document.head.appendChild(pdfjsLib);
            pdfjsLib.onload = function() {
              pdfjsLib.getDocument('$pdfUrl').promise.then(function(pdf) {
                pdf.getPage(1).then(function(page) {
                  var canvas = document.createElement('canvas');
                  document.body.appendChild(canvas);
                  var context = canvas.getContext('2d');
                  var viewport = page.getViewport({ scale: 1.0 });
                  canvas.height = viewport.height;
                  canvas.width = viewport.width;
                  page.render({
                    canvasContext: context,
                    viewport: viewport
                  });
                });
              }).catch(function(error) {
                console.error('PDF.js error: ' + error);
              });
            };
          ''');
                            }
                          }
                          pullToRefreshController?.endRefreshing();
                          return setState(() {
                            isLoading = false;
                          });
                        },
                        onReceivedError: (controller, request, error) {
                          pullToRefreshController?.endRefreshing();
                          return setState(() {
                            isLoading = false;
                          });
                        },
                        onProgressChanged: (controller, progress) {
                          if (progress == 100) {
                            pullToRefreshController?.endRefreshing();
                          }
                        },
                        onConsoleMessage: (controller, consoleMessage) {
                          if (kDebugMode) {
                            debugPrint("consoleMessage${consoleMessage}");
                          }
                          debugPrint(
                            "JavaScript console message: ${consoleMessage.message}",
                          );
                        },
                        // onDownloadStartRequest: (controller, url) async {
                        //   await ApiCalling.download_files(
                        //       empId, sessionId, "${url.url}", context)
                        //       .then((data) => {debugPrint(data)});
                        //
                        // },
                        onDownloadStartRequest: (
                          controller,
                          downloadStartRequest,
                        ) async {
                          if (Platform.isAndroid) {
                            await _handleDownload(
                              downloadStartRequest.url.toString(),
                              downloadStartRequest.suggestedFilename!,
                              downloadStartRequest.mimeType ??
                                  'application/octet-stream',
                              downloadStartRequest.suggestedFilename ?? '',
                            );
                          }
                        },
          
                      ),
                      if (isLoading) ...[
                        Container(
                          color: Colors.white.withOpacity(0.7),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              SpinKitRing(
                                color: AppColors.app_blue,
                                lineWidth: 4,
                                // duration: Duration(seconds: 2),
                                size: 50,
                              ),
                              const SizedBox(height: 15),
                              SizedBox(
                                width: 200,
                                child: Text(
                                  "Please wait.......",
                                  textAlign: TextAlign.center,
                                  style: TextStyle(
                                    decorationThickness: 0,
                                    fontSize: 15,
                                    fontWeight: FontWeight.normal,
                                    color: AppColors.app_blue,
                                  ),
                                ),
                              ),
          
                              // SvgPicture.asset("/assets/images/NutsLoader.gif")
                            ],
                          ),
                        ),
                      ],
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Future<void> _handleDownload(
    String url,
    String contentDisposition,
    String mimeType,
    String suggestedFilename,
  ) async {
    // Request notification permission for Android 13+
    if (Platform.isIOS) {
      _handleIOSDownload(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,
            });
          } else if (Platform.isIOS) {
            _handleIOSDownload(url, suggestedFilename);
          }
        } catch (e) {
          print("Download Error $e");
        }
      } else {
        toast(context, "Notification Permission Denied");
      }
    }
  }

  Future<void> _handleIOSDownload(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,
    );
  }
}

class SpinKitRing extends StatefulWidget {
  const SpinKitRing({
    Key? key,
    required this.color,
    this.lineWidth = 7.0,
    this.size = 50.0,
    this.duration = const Duration(milliseconds: 1200),
    this.controller,
  }) : super(key: key);

  final Color color;
  final double size;
  final double lineWidth;
  final Duration duration;
  final AnimationController? controller;

  @override
  State<SpinKitRing> createState() => _SpinKitRingState();
}

class _SpinKitRingState extends State<SpinKitRing>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation1;
  late Animation<double> _animation2;
  late Animation<double> _animation3;

  @override
  void initState() {
    super.initState();

    _controller =
        (widget.controller ??
              AnimationController(vsync: this, duration: widget.duration))
          ..addListener(() {
            if (mounted) {
              setState(() {});
            }
          })
          ..repeat();
    _animation1 = Tween(begin: 0.0, end: 1.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: const Interval(0.0, 1.0, curve: Curves.linear),
      ),
    );
    _animation2 = Tween(begin: -2 / 3, end: 1 / 2).animate(
      CurvedAnimation(
        parent: _controller,
        curve: const Interval(0.5, 1.0, curve: Curves.linear),
      ),
    );
    _animation3 = Tween(begin: 0.25, end: 5 / 6).animate(
      CurvedAnimation(
        parent: _controller,
        curve: const Interval(0.0, 1.0, curve: SpinKitRingCurve()),
      ),
    );
  }

  @override
  void dispose() {
    if (widget.controller == null) {
      _controller.dispose();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Transform(
        transform:
            Matrix4.identity()..rotateZ((_animation1.value) * 5 * pi / 6),
        alignment: FractionalOffset.center,
        child: SizedBox.fromSize(
          size: Size.square(widget.size),
          child: CustomPaint(
            foregroundPainter: RingPainter(
              paintWidth: widget.lineWidth,
              trackColor: widget.color,
              progressPercent: _animation3.value,
              startAngle: pi * _animation2.value,
            ),
          ),
        ),
      ),
    );
  }
}

class RingPainter extends CustomPainter {
  RingPainter({
    required this.paintWidth,
    this.progressPercent,
    this.startAngle,
    required this.trackColor,
  }) : trackPaint =
           Paint()
             ..color = trackColor
             ..style = PaintingStyle.stroke
             ..strokeWidth = paintWidth
             ..strokeCap = StrokeCap.square;

  final double paintWidth;
  final Paint trackPaint;
  final Color trackColor;
  final double? progressPercent;
  final double? startAngle;

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = (min(size.width, size.height) - paintWidth) / 2;
    canvas.drawArc(
      Rect.fromCircle(center: center, radius: radius),
      startAngle!,
      2 * pi * progressPercent!,
      false,
      trackPaint,
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

class SpinKitRingCurve extends Curve {
  const SpinKitRingCurve();

  @override
  double transform(double t) => (t <= 0.5) ? 2 * t : 2 * (1 - t);
}
