import 'dart:collection';

import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';

import '../../config/constants.dart';
import '../../config/theme.dart';
import '../../core/bridge/js_bridge.dart';
import 'offline_screen.dart';

class WebViewContainer extends StatefulWidget {
  final JsBridge bridge;
  final String? initialToken;
  final Function(InAppWebViewController) onControllerReady;
  final VoidCallback? onPageLoaded;
  final bool isOffline;

  const WebViewContainer({
    super.key,
    required this.bridge,
    required this.onControllerReady,
    this.initialToken,
    this.onPageLoaded,
    this.isOffline = false,
  });

  @override
  State<WebViewContainer> createState() => WebViewContainerState();
}

class WebViewContainerState extends State<WebViewContainer> {
  InAppWebViewController? _controller;
  bool _isLoading = true;
  bool _hasLoadError = false;
  double _progress = 0;
  bool _pageLoadedOnce = false;

  @override
  void didUpdateWidget(WebViewContainer oldWidget) {
    super.didUpdateWidget(oldWidget);
    // When connectivity comes back, auto-retry if we had an error
    if (oldWidget.isOffline && !widget.isOffline && _hasLoadError) {
      _retry();
    }
  }

  void _retry() {
    setState(() {
      _hasLoadError = false;
      _isLoading = true;
    });
    if (_pageLoadedOnce) {
      _controller?.reload();
    } else {
      _controller?.loadUrl(
        urlRequest: URLRequest(url: WebUri(AppConstants.webPlayerUrl)),
      );
    }
  }

  bool get _shouldShowOffline => _hasLoadError || (widget.isOffline && !_pageLoadedOnce);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        // WebView — always mounted so it keeps state, but hidden behind offline screen
        Opacity(
          opacity: _shouldShowOffline ? 0 : 1,
          child: IgnorePointer(
            ignoring: _shouldShowOffline,
            child: InAppWebView(
              initialUrlRequest: URLRequest(
                url: WebUri(AppConstants.webPlayerUrl),
              ),
              initialUserScripts: UnmodifiableListView([
                UserScript(
                  source: '''
                    window.IS_NATIVE_APP = true;
                    document.documentElement.classList.add('native-app');
                  ''',
                  injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START,
                ),
              ]),
              initialSettings: InAppWebViewSettings(
                javaScriptEnabled: true,
                domStorageEnabled: true,
                databaseEnabled: true,
                mediaPlaybackRequiresUserGesture: false,
                allowsInlineMediaPlayback: true,
                transparentBackground: true,
                userAgent:
                    'El3abApp/1.0 (Flutter; ${Theme.of(context).platform == TargetPlatform.iOS ? "iOS" : "Android"})',
                allowFileAccessFromFileURLs: false,
                allowUniversalAccessFromFileURLs: false,
                useShouldOverrideUrlLoading: true,
                supportZoom: false,
                disableHorizontalScroll: false,
                disableVerticalScroll: false,
                javaScriptCanOpenWindowsAutomatically: true,
                supportMultipleWindows: true,
              ),
              onWebViewCreated: (controller) {
                _controller = controller;
                widget.bridge.attach(controller);
                widget.onControllerReady(controller);

                controller.addJavaScriptHandler(
                  handlerName: 'flutter_bridge',
                  callback: (args) {
                    if (args.isNotEmpty) {
                      widget.bridge.handleMessage(args[0].toString());
                    }
                    return null;
                  },
                );
              },
              onLoadStart: (controller, url) {
                setState(() {
                  _isLoading = true;
                  _hasLoadError = false;
                });
              },
              onLoadStop: (controller, url) async {
                setState(() {
                  _isLoading = false;
                  _pageLoadedOnce = true;
                });

                await _injectBridgeScript();

                if (widget.initialToken != null) {
                  await _injectToken(widget.initialToken!);
                }

                widget.onPageLoaded?.call();
              },
              onProgressChanged: (controller, progress) {
                setState(() => _progress = progress / 100.0);
              },
              onReceivedError: (controller, request, error) {
                // Catch all WebView errors (no internet, DNS failure, timeout, etc.)
                final isMainFrame =
                    request.url.toString() == AppConstants.webPlayerUrl ||
                        request.isForMainFrame == true;
                if (isMainFrame) {
                  setState(() {
                    _hasLoadError = true;
                    _isLoading = false;
                  });
                }
              },
              onReceivedHttpError: (controller, request, response) {
                // Catch server errors (500, 502, 503, etc.)
                if (response.statusCode != null && response.statusCode! >= 500) {
                  final isMainFrame =
                      request.url.toString() == AppConstants.webPlayerUrl ||
                          request.isForMainFrame == true;
                  if (isMainFrame) {
                    setState(() {
                      _hasLoadError = true;
                      _isLoading = false;
                    });
                  }
                }
              },
              onCreateWindow: (controller, createWindowAction) async {
                // Handle OAuth popups (Google Sign-In etc.) — load in same WebView
                final url = createWindowAction.request.url;
                if (url != null) {
                  controller.loadUrl(urlRequest: URLRequest(url: url));
                }
                return true;
              },
              shouldOverrideUrlLoading: (controller, navigationAction) async {
                final uri = navigationAction.request.url;
                if (uri == null) return NavigationActionPolicy.CANCEL;

                final host = uri.host;
                final isAllowed = AppConstants.allowedDomains.any(
                  (domain) => host == domain || host.endsWith('.$domain'),
                );

                if (isAllowed) {
                  return NavigationActionPolicy.ALLOW;
                }

                return NavigationActionPolicy.CANCEL;
              },
              onConsoleMessage: (controller, consoleMessage) {
                debugPrint('[WebView] ${consoleMessage.message}');
              },
            ),
          ),
        ),

        // Native offline screen — covers WebView when there's an error
        if (_shouldShowOffline)
          Positioned.fill(
            child: OfflineScreen(onRetry: _retry),
          ),

        // Loading bar (only shows when actively loading, NOT when offline)
        if (_isLoading && !_shouldShowOffline)
          Positioned(
            top: 0,
            left: 0,
            right: 0,
            child: LinearProgressIndicator(
              value: _progress > 0 ? _progress : null,
              backgroundColor: Colors.transparent,
              valueColor: const AlwaysStoppedAnimation<Color>(El3abColors.gold),
              minHeight: 2,
            ),
          ),
      ],
    );
  }

  Future<void> _injectBridgeScript() async {
    if (_controller == null) return;

    const bridgeScript = '''
      (function() {
        if (window._el3ab_bridge_injected) return;
        window._el3ab_bridge_injected = true;

        window.flutter_bridge = {
          postMessage: function(message) {
            window.flutter_inappwebview.callHandler('flutter_bridge', message);
          }
        };

        window.el3ab_native = window.el3ab_native || {};
        window.IS_NATIVE_APP = true;
        document.documentElement.classList.add('native-app');

        console.log('[El3ab Native] Bridge injected');
      })();
    ''';

    await _controller!.evaluateJavascript(source: bridgeScript);
  }

  Future<void> _injectToken(String token) async {
    if (_controller == null) return;
    await _controller!.evaluateJavascript(
      source: '''
        (function() {
          var state = JSON.parse(localStorage.getItem('el3ab_state') || '{}');
          if (state.auth) {
            state.auth.token = '$token';
          }
          localStorage.setItem('el3ab_state', JSON.stringify(state));
          if (window.el3ab_native && window.el3ab_native.onTokenRefreshed) {
            window.el3ab_native.onTokenRefreshed({token: '$token'});
          }
        })();
      ''',
    );
  }

  Future<void> reload() async {
    _retry();
  }
}
