import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:in_app_review/in_app_review.dart';
import 'package:mypoint_flutter_app/core/utils/extensions/string_extension.dart';
import 'package:mypoint_flutter_app/core/network/restful_api_client_all_request.dart';
import 'package:mypoint_flutter_app/shared/preferences/data_preference.dart';
import 'package:mypoint_flutter_app/shared/widgets/alert/popup_data_model.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:uuid/uuid.dart';
import '../../app/config/constants.dart';
import '../../app/routing/app_navigator.dart';
import '../../core/network/restful_api_viewmodel.dart';
import '../../core/theme/base_color.dart';
import '../../features/pageDetail/model/detail_page_rule_type.dart';
import '../../features/pipi/pipi_detail_screen.dart';
import '../../features/webview/web_view_screen.dart';
import '../../core/services/logout_service.dart';
import '../router_gage.dart';
import '../widgets/alert/data_alert_model.dart';
import '../../app/routing/directional_action_type.dart';

class Defines {
  static const String actionType = 'click_action_type';
  static const String actionParams = 'click_action_param';
}

class DirectionalScreen {
  final String? clickActionType;
  final String? clickActionParam;
  final PopupDataModel? popup;
  Map<String, dynamic>? extraData = {};

  DirectionalScreen._({this.clickActionType, this.clickActionParam, this.popup});

  factory DirectionalScreen.fromJson(Map<String, dynamic> json) => DirectionalScreen._(
    clickActionType: json['click_action_type'] as String?,
    clickActionParam: json['click_action_param'] as String?,
  );

  Map<String, dynamic> toJson() => {
    'click_action_type': clickActionType,
    'click_action_param': clickActionParam,
  };

  static DirectionalScreen? build({String? clickActionType, String? clickActionParam}) {
    if ((clickActionType ?? "").isEmpty) return null;
    if (clickActionType == "VIEW_APP_SCREEN") {
      return DirectionalScreen._(clickActionType: clickActionParam, clickActionParam: null);
    }
    return DirectionalScreen._(clickActionType: clickActionType, clickActionParam: clickActionParam);
  }

  static DirectionalScreen? buildByName({required DirectionalScreenName name, String? clickActionParam}) {
    if (name == DirectionalScreenName.appScreen) {
      return DirectionalScreen._(clickActionType: clickActionParam, clickActionParam: null);
    }
    return DirectionalScreen._(clickActionType: name.rawValue, clickActionParam: clickActionParam);
  }

  bool begin() {
    final type = DirectionalScreenNameExtension.fromRawValue(clickActionType ?? "");
    switch (type) {
      case DirectionalScreenName.flashSale:
        Get.toNamed(flashSaleScreen, arguments: {"groupId": clickActionParam});
        return true;
      case DirectionalScreenName.brand:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(affiliateBrandDetailScreen, arguments: {"brandId": clickActionParam});
        return true;
      case DirectionalScreenName.preferentialHotList:
        Get.toNamed(vouchersScreen, arguments: {"isHotProduct": true});
        return true;
      case DirectionalScreenName.memberShip:
        Get.toNamed(membershipScreen);
        return true;
      case DirectionalScreenName.customerReviewApp:
        final storeUrl = 'https://itunes.apple.com/app/id${Constants.appStoreId}?action=write-review';
        openStringUrlExternally(storeUrl);
        return true;
      case DirectionalScreenName.rateStorePopup:
        _requestAppReview();
        return false;
      case DirectionalScreenName.pipiScreen:
        Get.bottomSheet(const PipiDetailScreen(), isScrollControlled: true, backgroundColor: Colors.transparent);
        return true;
      case DirectionalScreenName.viewVoucherWithCountTime:
        final countDownSecond = int.tryParse(clickActionParam ?? '') ?? 0;
        Get.toNamed(vouchersScreen, arguments: {"countDownSecond": countDownSecond});
        return true;
      case DirectionalScreenName.popViewController:
        if (Get.isOverlaysOpen) {
          Get.back();
          return true;
        }
        if (Get.key.currentState?.canPop() == true) {
          Get.back();
          return true;
        }
        return false;
      case DirectionalScreenName.finishScreen:
        Get.until((route) => route.isFirst);
        return true;
      case DirectionalScreenName.luckyMoney:
        if (clickActionParam.orEmpty.isEmpty) return false;
        BaseWebViewInput input = BaseWebViewInput(url: clickActionParam.orEmpty.urlDecoded);
        Get.toNamed(baseWebViewScreen, arguments: input);
        return true;
      case DirectionalScreenName.privacyPolicy:
        Get.toNamed(campaignDetailScreen, arguments: {"type": DetailPageRuleType.privacyPolicy});
        return true;
      case DirectionalScreenName.termsOfUse:
        Get.toNamed(campaignDetailScreen, arguments: {"type": DetailPageRuleType.termsOfUse});
        return true;
      case DirectionalScreenName.termPolicyDecree13:
        Get.toNamed(campaignDetailScreen, arguments: {"type": DetailPageRuleType.decree});
        return true;
      case DirectionalScreenName.termPolicyDeleteAccount:
        Get.toNamed(campaignDetailScreen, arguments: {"type": DetailPageRuleType.policyDeleteAccount});
        return true;
      case DirectionalScreenName.familyMedonDetailCard:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(healthBookCardDetail, arguments: {"id": clickActionParam});
        return false;
      case DirectionalScreenName.webviewFullScreen:
        if ((clickActionParam ?? '').isEmpty) return false;
        BaseWebViewInput input = BaseWebViewInput(url: clickActionParam ?? "", isFullScreen: true);
        Get.toNamed(baseWebViewScreen, arguments: input);
        return true;
      case DirectionalScreenName.gameCardDetail:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(gameCardScreen, arguments: {"gameId": clickActionParam ?? ''});
        return true;
      case DirectionalScreenName.inviteFriend ||
          DirectionalScreenName.customerInviteFriend ||
          DirectionalScreenName.newInviteFriend ||
          DirectionalScreenName.inviteFriendApply:
        Get.toNamed(inviteFriendCampaignScreen);
        return true;
      case DirectionalScreenName.personal:
        Get.toNamed(personalEditScreen);
        return true;
      case DirectionalScreenName.viewSMS:
        final parts = clickActionParam.orEmpty.split('_');
        if (parts.length != 2) return false;
        final phone = parts[0].trim();
        final content = parts[1].trim();
        final contentDecoded = Uri.decodeComponent(content);
        final body = Uri.encodeComponent(contentDecoded);
        // iOS: &body=..., Android: ?body=...
        final isIOS = defaultTargetPlatform == TargetPlatform.iOS;
        final urlStr = isIOS
            ? 'sms:$phone&body=$body'
            : 'sms:$phone?body=$body';
        final uri = Uri.parse(urlStr);
        debugPrint('Mở SMS: $uri phone=$phone, content=$content');
        _openUrlExternally(uri);
        return false;
      case DirectionalScreenName.setting:
        Get.toNamed(settingScreen);
        return true;
      case DirectionalScreenName.productOwnVoucher:
        Get.toNamed(voucherDetailScreen, arguments: {"customerProductId": int.parse(clickActionParam ?? "")});
        return true;
      case DirectionalScreenName.customerSupport:
        Get.toNamed(supportScreen);
        return true;
      case DirectionalScreenName.link:
        BaseWebViewInput input = BaseWebViewInput(url: clickActionParam ?? "");
        Get.toNamed(baseWebViewScreen, arguments: input);
        return true;
      case DirectionalScreenName.website|| DirectionalScreenName.introduction:
        Get.toNamed(campaignDetailScreen, arguments: {"id": clickActionParam ?? ""});
        return true;
      case DirectionalScreenName.gameCenter:
        Get.toNamed(vplayGameCenterScreen);
        return true;
       case DirectionalScreenName.viewAllVoucher ||
          DirectionalScreenName.searchProduct ||
          DirectionalScreenName.productVoucher:
        Get.toNamed(vouchersScreen, arguments: {"enableSearch": true});
        return true;
      case DirectionalScreenName.news:
        Get.toNamed(newsListScreen);
        return true;
      case DirectionalScreenName.gifts:
        Get.toNamed(achievementListScreen);
        return true;
      case DirectionalScreenName.pointHunting || DirectionalScreenName.achievement:
        Get.toNamed(achievementListScreen, arguments: true);
        return true;
      case DirectionalScreenName.myPurchaseItems || DirectionalScreenName.myPurchaseItemsWaitingList:
        Get.toNamed(myVoucherListScreen);
        return true;
      case DirectionalScreenName.orderMenu:
        Get.toNamed(orderMenuScreen);
        return true;
      case DirectionalScreenName.topup || DirectionalScreenName.mobileTopup:
        Get.toNamed(phoneTopUpScreen);
        return true;
      case DirectionalScreenName.productMobileCard:
        Get.toNamed(productMobileCardScreen);
        return true;
      case DirectionalScreenName.simService:
        BaseWebViewInput input = BaseWebViewInput(url: "https://mypoint.uudaigoicuoc.com/");
        Get.toNamed(baseWebViewScreen, arguments: input);
        return true;
      case DirectionalScreenName.mobileTopupData:
        Get.toNamed(dataNetworkServiceScreen);
        return true;
      case DirectionalScreenName.pointBack:
        Get.toNamed(affiliateTabScreen, arguments: {"can_back_button": true});
        return true;
      case DirectionalScreenName.gamesBundle:
        Get.toNamed(gameTabScreen, arguments: {"can_back_button": true});
        return true;
      case DirectionalScreenName.vnTraPackage || DirectionalScreenName.familyMedon || DirectionalScreenName.voucher:
        Get.toNamed(voucherDetailScreen, arguments: {"productId": int.parse(clickActionParam ?? "")});
        return true;
      case DirectionalScreenName.viewDeepLink || DirectionalScreenName.viewDeepLinkInApp:
        if ((clickActionParam ?? "").isEmpty) return true;
        const replaceId1 = '{{customerId}}';
        const replaceId2 = '{customerId}';
        final customerId = DataPreference.instance.profile?.workerSite?.customerId ?? "";
        String urlString = clickActionParam!.urlDecoded;
        if (urlString.contains(replaceId1)) {
          urlString = urlString.replaceAll(replaceId1, customerId);
        }
        if (urlString.contains(replaceId2)) {
          urlString = urlString.replaceAll(replaceId2, customerId);
        }
        // Parse thành Uri và thêm query aff_sub3
        Uri? uri = Uri.tryParse(urlString);
        if (uri == null) return true;
        final requestId = const Uuid().v4(); // Cần package `uuid`
        final updatedUri = uri.replace(queryParameters: {...uri.queryParameters, 'aff_sub3': requestId});
        LaunchMode mode =
            type == DirectionalScreenName.viewDeepLink ? LaunchMode.externalApplication : LaunchMode.inAppWebView;
        // forceOpen(url: updatedUri, mode: mode);
        _safeOpenUrl(updatedUri, preferred: mode);
        return true;
      case DirectionalScreenName.refundHistory:
        Get.toNamed(historyPointCashBackScreen);
        return true;
      case DirectionalScreenName.dailyCheckin || DirectionalScreenName.dailyCheckinScreen:
        Get.toNamed(dailyCheckInScreen);
        return true;
      case DirectionalScreenName.favorite || DirectionalScreenName.productVoucherLike:
        Get.toNamed(vouchersScreen, arguments: {"favorite": true});
        return true;
      case DirectionalScreenName.transactionHistories:
        Get.toNamed(transactionHistoryScreen);
        return true;
      case DirectionalScreenName.electricBill:
        Get.toNamed(electricPaymentScreen);
        return true;
      case DirectionalScreenName.listPaymentOfElectric:
        Get.toNamed(electricPaymentHistoryScreen);
        return true;
      case DirectionalScreenName.myVnTraPackage:
        Get.toNamed(trafficServiceScreen);
        return true;
      case DirectionalScreenName.familyHealthBook:
        Get.toNamed(healthBookScreen);
        return true;
      case DirectionalScreenName.campaignSevenDayScreen:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(campaignSevenDayScreen, arguments: {"id": clickActionParam});
        return true;
      case DirectionalScreenName.workerProfile:
        Get.toNamed(personalEditScreen);
        return true;
      case DirectionalScreenName.surveyCampaign:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(surveyQuestionScreen, arguments: {"quizId": clickActionParam ?? ''});
        return true;
      case DirectionalScreenName.myMobileCard:
        Get.toNamed(myMobileCardListScreen);
        return true;
      case DirectionalScreenName.bankAccountManager:
        Get.toNamed(bankAccountManagerScreen);
        return true;
      case DirectionalScreenName.pointHistory:
        Get.toNamed(historyPointScreen);
        return true;
      case DirectionalScreenName.qrCode:
        Get.toNamed(qrCodeScreen);
        return true;
      case DirectionalScreenName.makeDirectionScreen:
        if ((clickActionParam ?? '').isEmpty) return false;
        () async {
          final vm = RestfulApiViewModel();
          await vm.callApi<DirectionalScreen>(
            request: () => vm.client.getDirectionScreen(clickActionParam!),
            onSuccess: (screen, res) async {
              final popup = screen.popup;
              if (popup != null) {
                AppNavigator.showPopup(data: popup);
              } else {
                screen.begin();
              }
            },
            withLoading: true,
            showAppNavigatorDialog: false,
          );
        }();
        return true;
      case DirectionalScreenName.linkMBPAccount:
        if ((clickActionParam ?? '').isEmpty) return false;
        _handleLinkMBPAccount();
        return true;
        case DirectionalScreenName.notifications:
        Get.toNamed(notificationScreen);
        return true;
      case DirectionalScreenName.notification:
        if ((clickActionParam ?? '').isEmpty) {
          final title = (extraData?['title'] as String?).orEmpty;
          final body = (extraData?['body'] as String?).orEmpty;
          if (title.isNotEmpty && body.isNotEmpty) {
            Get.toNamed(notificationDetailScreen, arguments: {"title": title, "body": body});
            return true;
          }
          return false;
        }
        Get.toNamed(notificationDetailScreen, arguments: {"notificationId": clickActionParam});
        return true;
      case DirectionalScreenName.detailTrafficService:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(trafficServiceDetailScreen, arguments: {"serviceId": clickActionParam});
        return true;
      case DirectionalScreenName.appScreen:
        if ((clickActionParam ?? '').isEmpty) return false;
        final direction = DirectionalScreen.build(clickActionType: clickActionParam);
        direction?.begin();
        return true;
      case DirectionalScreenName.transaction:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(transactionHistoryDetailScreen, arguments: {"orderId": clickActionParam});
        return true;
      case DirectionalScreenName.applicationSetting:
        openAppSettings();
        return true;
      case DirectionalScreenName.cashBackPointPartnerDetail:
        if ((clickActionParam ?? '').isEmpty) return false;
        Get.toNamed(affiliateBrandDetailScreen, arguments: {"brandId": clickActionParam});
        return true;
      // case DirectionalScreenName.historyInvitedFriend:
      // case DirectionalScreenName.screenAddInvitationCode:
      // Deprecated / unsupported entries kept in enum for backward compatibility.
      case DirectionalScreenName.flashSale ||
          DirectionalScreenName.viewGift ||
          DirectionalScreenName.feedback ||
          DirectionalScreenName.ranking ||
          DirectionalScreenName.inputReferralCode ||
          DirectionalScreenName.shoppingOnline ||
          DirectionalScreenName.partnerRedirect ||
          DirectionalScreenName.brandOffline ||
          DirectionalScreenName.customerTransferPoint ||
          DirectionalScreenName.home ||
          DirectionalScreenName.brandList ||
          DirectionalScreenName.brandLike ||
          DirectionalScreenName.register ||
          DirectionalScreenName.walkingCampaign ||
          DirectionalScreenName.gameWorldCup2022 ||
          DirectionalScreenName.vietlott ||
          DirectionalScreenName.unknown:
        _logUnsupported(type);
        return false;
      default:
        debugPrint("Không nhận diện được action type: $clickActionType");
        return false;
    }
  }

  void _logUnsupported(DirectionalScreenName type) {
    debugPrint("⚠️ DirectionalScreen action type không được hỗ trợ: ${type.rawValue}");
  }

  void _handleLinkMBPAccount() {
    final phone = clickActionParam.orEmpty;
    if (phone.isEmpty) return;
    final password = extraData?['password'] as String? ?? '';
    if (!DataPreference.instance.logged) {
      _gotoLoginScreen(phone, password);
      return;
    }
    final currentPhone = DataPreference.instance.phone.orEmpty;
    if (phone == currentPhone || currentPhone.isEmpty) return;
    final dataAlert = DataAlertModel(
      title: "Xác nhận",
      description: "Bạn muốn đăng xuất để login tài khoản($phone) vừa liên kết không?",
      localHeaderImage: "assets/images/ic_pipi_03.png",
      buttons: [
        AlertButton(
          text: "Đồng ý",
          onPressed: () async {
            Get.back();
            _gotoLoginScreen(phone, password);
            debugPrint("Đồng ý đăng xuất để liên kết tài khoản $phone");
          },
          bgColor: BaseColor.primary500,
          textColor: Colors.white,
        ),
        AlertButton(text: "Huỷ", onPressed: () => Get.back(), bgColor: Colors.white, textColor: BaseColor.second500),
      ],
    );
    AppNavigator.showAlert(data: dataAlert, showCloseButton: false);
  }

  Future<void> _gotoLoginScreen(String phone, String password) async {
    await LogoutService.logout();
    await DataPreference.instance.clearData();
    Get.offAllNamed(loginScreen, arguments: {"phone": phone, 'password': password});
  }
}

Future<bool> forceOpen({required Uri url, LaunchMode mode = LaunchMode.platformDefault}) async {
    debugPrint("force open ${url.toString()}");
  if (await canLaunchUrl(url)) {
    await launchUrl(
      url,
      mode: LaunchMode.inAppBrowserView,
      webViewConfiguration: const WebViewConfiguration(enableJavaScript: true, headers: <String, String>{}),
    );
    return true;
  }
  return false;
}

Future<void> openStringUrlExternally(String url) async {
  final uri = Uri.parse(url);
  _openUrlExternally(uri);
}

Future<void> _openUrlExternally(Uri uri) async {
  if (await canLaunchUrl(uri)) {
    await launchUrl(uri, mode: LaunchMode.externalApplication);
  } else {
    debugPrint("⚠️ Không thể mở URL: $uri");
  }
}

Future<bool> _safeOpenUrl(Uri url, {LaunchMode preferred = LaunchMode.platformDefault}) async {
  try {
    // Nếu không mở được bằng bất kỳ hình thức nào thì dừng sớm
    if (!await canLaunchUrl(url)) return false;

    // Sắp xếp các chế độ theo ưu tiên và loại bỏ trùng lặp
    final List<LaunchMode> modes = <LaunchMode>[
      preferred,
      LaunchMode.externalApplication,
      LaunchMode.inAppBrowserView,
      LaunchMode.platformDefault,
    ];
    final Set<LaunchMode> seen = <LaunchMode>{};

    for (final mode in modes) {
      if (!seen.add(mode)) continue;
      try {
        final ok = await launchUrl(
          url,
          mode: mode,
          webViewConfiguration: const WebViewConfiguration(
            enableJavaScript: true,
            headers: <String, String>{},
          ),
        );
        if (ok) return true;
      } catch (_) {
        // thử chế độ tiếp theo
      }
    }
  } catch (_) {}
  return false;
}

Future<void> _requestAppReview() async {
  final inAppReview = InAppReview.instance;
  if (await inAppReview.isAvailable()) {
    await inAppReview.requestReview();
    return;
  }
  // Fallback mở trang app trên store
  await inAppReview.openStoreListing(appStoreId: Constants.appStoreId, microsoftStoreId: null);
}
