import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/shared/widgets/back_button.dart';
import 'package:mypoint_flutter_app/shared/widgets/custom_toast_message.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../shared/widgets/loading/app_loading.dart';
import '../../shared/widgets/base_view/base_screen.dart';
import '../../shared/widgets/base_view/basic_state.dart';
import '../../shared/navigation/directional_screen.dart';
import '../../shared/widgets/custom_navigation_bar.dart';
import '../../shared/preferences/data_preference.dart';
import '../../core/services/package_info.dart';

/// Payload for launching [BaseWebViewScreen].
class BaseWebViewInput {
  final String? title;
  final String url;
  final bool isFullScreen;

  const BaseWebViewInput({
    this.title,
    required this.url,
    this.isFullScreen = false,
  });
}

class BaseWebViewScreen extends BaseScreen {
  const BaseWebViewScreen({super.key});

  @override
  State<BaseWebViewScreen> createState() => _BaseWebViewScreenState();
}

/// Hosts a platform-aware WebView that mirrors native behaviour on iOS/Android
/// while delegating to the browser on Flutter web builds.
class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen>
    with BasicState {
  late final BaseWebViewInput input;
  WebViewController? _webViewController; // Null khi chạy Flutter web
  String? _dynamicTitle;
  Map<String, String>? _authHeaders;
  bool _isReissuingNavigation = false;

  @override
  void initState() {
    super.initState();
    if (!_hydrateArguments()) return;
    if (_handleWebPlatformLaunch()) return;
    _initializeMobileController();
  }

  bool _hydrateArguments() {
    final args = Get.arguments;
    if (args is BaseWebViewInput && args.url.isNotEmpty) {
      input = args;
      return true;
    }
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (Get.key.currentState?.canPop() ?? false) {
        Get.back();
      } else if (mounted) {
        Navigator.of(context).maybePop();
      }
    });
    return false;
  }

  bool _handleWebPlatformLaunch() {
    if (!kIsWeb) return false;
    AppLoading().hide();
    Future.microtask(() async {
      await _openUrlInBrowser();
      if (mounted && Navigator.of(context).canPop()) {
        Navigator.of(context).pop();
      }
    });
    return true;
  }

  void _initializeMobileController() {
    AppLoading().show();
    _webViewController =
        WebViewController()
          ..setJavaScriptMode(JavaScriptMode.unrestricted)
          ..setBackgroundColor(Colors.transparent)
          ..setNavigationDelegate(
            NavigationDelegate(
              onPageFinished: (_) async {
                AppLoading().hide();
                final title = await _webViewController!.getTitle();
                setState(() {
                  _dynamicTitle = title;
                });
              },
              onWebResourceError: (error) {
                AppLoading().hide();
                if (error.description != 'about:blank') {
                  debugPrint('WebView error: ${error.description}');
                  // Có thể hiển thị lỗi nếu cần
                  showAlertError(content: error.description);
                }
              },
              onNavigationRequest: _handleNavigation,
            ),
          );
    _prepareInitialLoad();
  }

  String formatUrl(String inputUrl) {
    if (inputUrl.isEmpty) return '';
    try {
      if (!inputUrl.startsWith('http://') && !inputUrl.startsWith('https://')) {
        return 'https://$inputUrl';
      }
      return inputUrl;
    } catch (e) {
      debugPrint('Failed to format URL: $inputUrl - $e');
      return inputUrl;
    }
  }

  @override
  Widget createBody() {
    // Web platform: không hiển thị màn hình trung gian (đã auto mở tab mới ở initState)
    if (kIsWeb) {
      return const SizedBox.shrink();
    }
    // Mobile platform: sử dụng WebView
    return Scaffold(
      appBar:
          input.isFullScreen
              ? null
              : CustomNavigationBar(
                title:
                    input.title ?? _dynamicTitle ?? Uri.parse(input.url).host,
                leftButtons: [CustomBackButton(onPressed: _handleBack)],
              ),
      body: Stack(
        children: [
          SafeArea(
            child: WebViewWidget(
              controller: _webViewController!,
              gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{
                Factory<VerticalDragGestureRecognizer>(
                  VerticalDragGestureRecognizer.new,
                ),
              },
            ),
          ),
          if (input.isFullScreen)
            Positioned(
              top: MediaQuery.of(context).padding.top + 8,
              left: 8,
              child: CustomBackButton(),
            ),
        ],
      ),
    );
  }

  Future<void> _clearCookies() async {
    if (kIsWeb) return; // Web không cần clear cookies
    final cookieManager = WebViewCookieManager();
    await cookieManager.clearCookies();
  }

  void _handleBack() async {
    if (kIsWeb) {
      // Web: chỉ đơn giản quay lại
      if (context.mounted) Navigator.of(context).pop();
      return;
    }

    // Mobile: kiểm tra WebView có thể go back không
    if (_webViewController != null && await _webViewController!.canGoBack()) {
      _webViewController!.goBack();
    } else {
      if (context.mounted) Navigator.of(context).pop();
    }
  }

  Future<void> _openUrlInBrowser() async {
    try {
      final uri = Uri.parse(formatUrl(input.url));
      if (await canLaunchUrl(uri)) {
        await launchUrl(uri, mode: LaunchMode.externalApplication);
      } else {
        debugPrint('Could not launch URL: ${input.url}');
      }
    } catch (e) {
      debugPrint('Error launching URL: $e');
    }
  }

  NavigationDecision _handleNavigation(NavigationRequest request) {
    final url = request.url;
    debugPrint("➡️ Navigating: $url");
    if (url.isEmpty || url == 'about:blank') {
      return NavigationDecision.prevent;
    }
    if (_isDataImageUrl(url)) {
      _processDataImageUrl(url);
      return NavigationDecision.prevent;
    }
    if (url.startsWith('itms-apps://')) {
      openStringUrlExternally(url);
      return NavigationDecision.prevent;
    }
    if (url.startsWith('sms:')) {
      final uri = Uri.parse(url);
      launchUrl(uri);
      return NavigationDecision.prevent;
    }
    debugPrint('🔗 Handling navigation to URL: $url');
    if (_isReissuingNavigation) {
      _isReissuingNavigation = false;
      return NavigationDecision.navigate;
    }

    if (_shouldAttachHeaders(url)) {
      debugPrint('🔄 Reissuing navigation with headers to URL: $url');
      try {
        final target = Uri.parse(url);
        _loadWithHeaders(target);
        return NavigationDecision.prevent;
      } catch (e) {
        debugPrint('Failed to reissue navigation with headers: $e');
      }
    }
    final uri = Uri.tryParse(url);
    if (uri != null) {
      if (uri.scheme == 'mypointapp') {
        final action = uri.queryParameters['click_action_type'] ?? '';
        final direction = DirectionalScreen.build(
          clickActionType: action,
          clickActionParam: '',
        );
        final directionSuccess = direction?.begin();
        if (directionSuccess != true) {
          launchUrl(uri, mode: LaunchMode.externalApplication);
          return NavigationDecision.prevent;
        }
      }
      // Bất kỳ scheme không phải http/https: cố gắng mở ngoài
      if (uri.scheme.isNotEmpty &&
          uri.scheme != 'http' &&
          uri.scheme != 'https') {
        launchUrl(uri, mode: LaunchMode.externalApplication);
        return NavigationDecision.prevent;
      }
    }
    debugPrint('✅ Allowing navigation to URL: $url');
    return NavigationDecision.navigate;
  }

  /// Performs the first load by cleaning stale cookies, attaching auth headers,
  /// and retrying without headers when the secure load fails (e.g., CORS).
  Future<void> _prepareInitialLoad() async {
    await _clearCookies();
    final formattedUrl = formatUrl(input.url);
    if (formattedUrl.isEmpty) {
      AppLoading().hide();
      return;
    }
    var uri = Uri.parse(formattedUrl);
    final token = DataPreference.instance.token?.trim();
    if (token != null &&
        token.isNotEmpty &&
        defaultTargetPlatform == TargetPlatform.iOS) {
      final query = Map<String, String>.from(uri.queryParameters);
      query['access_token'] = token;
      uri = uri.replace(queryParameters: query);
    }
    await _syncAuthCookie(uri);
    final headers = await _buildInitialHeaders();
    _authHeaders = headers.isEmpty ? null : headers;
    try {
      await _loadWithHeaders(uri);
    } catch (e) {
      debugPrint(
        'WebView load with headers failed: $e. Retrying without headers.',
      );
      await _webViewController?.loadRequest(uri);
    }
  }

  /// Synchronises token cookies with the WebView so native and web share a session.
  Future<void> _syncAuthCookie(Uri uri) async {
    if (!DataPreference.instance.logged) return;
    final token = DataPreference.instance.token?.trim();
    if (token == null || token.isEmpty) return;
    final cookieManager = WebViewCookieManager();
    await cookieManager.setCookie(
      WebViewCookie(
        name: 'access_token',
        value: token,
        domain: uri.host,
        path: '/',
      ),
    );
  }

  Future<Map<String, String>> _buildInitialHeaders() async {
    if (!DataPreference.instance.logged) return {};
    final token = DataPreference.instance.token?.trim();
    if (token == null || token.isEmpty) return {};
    try {
      final version = await AppInfoHelper.version;
      return {
        'access_token': token,
        'version': version,
        'Cookie': 'access_token=$token'
      };
    } catch (_) {
      return {'access_token': token, 'Cookie': 'access_token=$token'};
    }
  }

  Future<void> _loadWithHeaders(Uri uri) async {
    if (_authHeaders == null || _authHeaders!.isEmpty) {
      await _webViewController?.loadRequest(uri);
      return;
    }
    _isReissuingNavigation = true;
    debugPrint(
      '➡️ Loading with headers: ${uri.toString()}, headers: $_authHeaders',
    );
    await _webViewController?.loadRequest(uri, headers: _authHeaders!);
  }

  bool _shouldAttachHeaders(String url) {
    if (_authHeaders == null || _authHeaders!.isEmpty) return false;
    if (url.isEmpty || url == 'about:blank') return false;
    final lower = url.toLowerCase();
    return lower.startsWith('http://') || lower.startsWith('https://');
  }

  bool _isDataImageUrl(String url) => url.startsWith('data:image');

  void _processDataImageUrl(String url) {
    Future.microtask(() => _saveBase64Image(url));
  }

  Future<void> _saveBase64Image(String url) async {
    if (!mounted || kIsWeb) return;
    final payload = _extractBase64Payload(url);
    if (payload == null) {
      _showSnack('Không thể đọc dữ liệu ảnh.');
      return;
    }
    final hasPermission = await _ensureMediaPermission();
    if (!hasPermission) {
      _showSnack(
        'Ứng dụng chưa có quyền lưu ảnh. Vui lòng cấp quyền trong cài đặt.',
      );
      return;
    }
    try {
      final Uint8List bytes = base64Decode(payload);
      final result = await ImageGallerySaver.saveImage(
        bytes,
        quality: 100,
        name: 'mypoint_${DateTime.now().millisecondsSinceEpoch}',
      );
      final success =
          (result['isSuccess'] ?? result['success'] ?? result['status']) ==
          true;
      _showSnack(
        success ? 'Ảnh đã được lưu vào thư viện.' : 'Không thể lưu ảnh.',
      );
    } catch (e) {
      debugPrint('Failed to save base64 image: $e');
      _showSnack('Không thể lưu ảnh.');
    }
  }

  String? _extractBase64Payload(String url) {
    final marker = 'base64,';
    final index = url.indexOf(marker);
    if (index == -1) return null;
    return url.substring(index + marker.length).trim();
  }

  Future<bool> _ensureMediaPermission() async {
    if (kIsWeb) return false;
    PermissionStatus status;
    if (defaultTargetPlatform == TargetPlatform.iOS) {
      status = await Permission.photosAddOnly.request();
      if (status.isGranted) return true;
      status = await Permission.photos.request();
      if (status.isGranted) return true;
    } else {
      status = await Permission.photos.request();
      if (status.isGranted) return true;
      status = await Permission.storage.request();
      if (status.isGranted || status.isLimited) return true;
    }
    if (status.isPermanentlyDenied && kDebugMode) {
          debugPrint('Media permission permanently denied.');
    }
    return false;
  }

  void _showSnack(String message) {
    if (!mounted) return;
    showToastMessage(message);
  }
}
