import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'package:puzzleweave/ads/applovin_ads_controller.dart';
import 'package:puzzleweave/audio/jc_audio_controller.dart';
import 'package:puzzleweave/collection/collection_screen.dart';
import 'package:puzzleweave/config/config.dart';
import 'package:puzzleweave/config/device.dart';
import 'package:puzzleweave/firebase/adjust_helper.dart';
import 'package:puzzleweave/homepage/home_board_play.dart';
import 'package:puzzleweave/l10n/app_localizations.dart';
import 'package:puzzleweave/models/cached_request.dart';
import 'package:puzzleweave/models/download.dart';
import 'package:puzzleweave/models/items.dart';
import 'package:puzzleweave/persistence/persistence.dart';
import 'package:puzzleweave/play/board_play.dart';
import 'package:puzzleweave/settings/settings_screen.dart';
import 'package:puzzleweave/skin/skin.dart';
import 'package:puzzleweave/utils/mybutton.dart';
import 'package:puzzleweave/utils/utils.dart';

import '../ads/ad_helper.dart';
import '../ads/ads_state.dart';
import '../utils/memory_monitor.dart';

final Logger _log = Logger('home_screen');

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<StatefulWidget> createState() => _HomeScreen();
}

const int minimumRemoteLoadCount = 30;

class _HomeScreen extends AdsState<HomeScreen> with TickerProviderStateMixin {
  late Device device;
  late JcAudioController audio;
  List<ListItem>? latest;
  late CachedRequest latestCachedRequest;
  late StreamSubscription? latestSubscription;

  final _canvasKey = GlobalKey<HomeBoardPlayState>();
  final GlobalKey _collectionKey = GlobalKey();

  bool isLoading = true;
  bool firstRun = false;

  // ✅ 优化点1: 导航状态管理
  bool _isNavigating = false;

  // ✅ 优化点2: 防抖机制
  Timer? _refreshDebouncer;

  // ✅ 优化点3: 缓存计算结果
  double? _cachedCanvasWidth;
  double? _cachedCanvasHeight;
  bool _layoutCalculated = false;

  late AnimationController _collectionController;
  late Animation<double> _collectionAnimation;

  bool interPending = false;

  @override
  void initState() {
    super.initState();
    _log.info("首页初始化");

    _initializeComponents();
    _setupAnimations();
    _handleInitialNavigation();
  }

  void _initializeComponents() {
    device = context.read<Device>();
    audio = context.read<JcAudioController>();
    latestCachedRequest = data.latest;

    final cachedData = latestCachedRequest.cachedData;
    if (cachedData != null) {
      _onLatestDataUpdate(cachedData);
    }
    latestSubscription = latestCachedRequest.stream.listen(_onLatestDataUpdate, onError: _onLatestDataError);

    onInterstitialAdState = _createInterStateListener();
  }

  Function(AdState state) _createInterStateListener() {
    return (AdState state) {
      _log.info('Interstitial ad state changed: $state');
      if (state == AdState.dismissed && interPending) {
        _log.info('Interstitial ad dismissed, executing pending post-ad logic.');
        _canvasKey.currentState?.startFlipAnimation();

        final bool hasSufficientData = latest != null && latest!.length >= minimumRemoteLoadCount;
        final bool isNetworkActive = latestCachedRequest.hasRecentSuccessfulFetch;

        if (hasSufficientData) {
          if (isNetworkActive) {
            _log.info('Game finished, data complete & Network Active. Triggering sequential preloading...');
            _preloadNextImages();
          } else {
            _log.info('Game finished, data complete but Network inactive. Attempting refresh.');
            refresh();
          }
        } else {
          _log.info('Game finished, remote data incomplete. Attempting refresh...');
          refresh();
        }
        interPending = false;
      }
    };
  }

  void _setupAnimations() {
    _collectionController = AnimationController(duration: const Duration(milliseconds: 300), vsync: this)
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          audio.playSfx(SfxType.pop);
        }
      });

    _collectionAnimation = TweenSequence<double>([
      TweenSequenceItem(tween: Tween<double>(begin: 1.0, end: 1.4).chain(CurveTween(curve: Curves.easeOut)), weight: 40.0),
      TweenSequenceItem(tween: Tween<double>(begin: 1.4, end: 1.0).chain(CurveTween(curve: Curves.easeIn)), weight: 60.0),
    ]).animate(_collectionController);
  }

  void _handleInitialNavigation() {
    if (Persistence().firstRun) {
      firstRun = true;
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted && !_isNavigating) {
          _handleFirstRunNavigation();
        }
      });
      Persistence().firstRun = false;
    }

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed && mounted) {
        audio.startMusic();
      }
    });
  }

  // ✅ 优化点4: 异步化首次运行导航
  void _handleFirstRunNavigation() {
    if (_isNavigating) return;

    _log.info('First run detected, navigating to initial play page.');
    final AssetItem initialItem = AssetItem(
      Config.firstId,
      '',
      2000,
      3000,
      3,
      false,
      'assets/builtin/${Config.firstId}.jpeg',
      'assets/builtin/${Config.firstId}.jpeg',
    );
    return gotoPlay(initialItem, firstRun: true);
  }

  // ✅ 优化点5: 异步化文件检查
  void checkGoPlay() {
    if (currentItem == null || _isNavigating) return;

    Future.microtask(() async {
      try {
        final jsonFile = await localFile(currentItem!.jsonPath);
        final exists = await jsonFile.exists();

        if (mounted && exists && !_isNavigating) {
          gotoPlay(currentItem!);
        }
      } catch (e) {
        _log.warning('Error checking play file: $e');
      }
    });
  }

  @override
  void dispose() {
    _refreshDebouncer?.cancel();
    latestSubscription?.cancel();
    _collectionController.dispose();
    super.dispose();
  }

  // ✅ 优化点6: 简化数据更新逻辑
  _onLatestDataUpdate(datalist) {
    _log.info('_onLatestDataUpdate....');
    if (datalist == null) return;

    bool shouldCheckGoPlay = false;
    if (currentItem == null && !firstRun) {
      shouldCheckGoPlay = true;
    }

    latest = datalist as List<ListItem>;
    isLoading = false;
    setState(() {});

    final bool hasSufficientData = datalist.length >= minimumRemoteLoadCount;
    final bool isNetworkActive = latestCachedRequest.hasRecentSuccessfulFetch;

    if (hasSufficientData) {
      if (!hasInit) {
        initThird();
      }
      if (!isNetworkActive) {
        _debouncedRefresh();
      }
    } else {
      _log.info('Data insufficient (only ${datalist.length} items). Attempting refresh.');
      _debouncedRefresh();
    }

    if (shouldCheckGoPlay) {
      checkGoPlay();
    }
  }

  _onLatestDataError(error) {
    _log.info('_onLatestDataError.... $error');
    if (latest == null || latest!.isEmpty || latest!.length < 20) {
      _log.warning("_onLatestDataError, retry again");
      _debouncedRefresh();
    }
  }

  // ✅ 优化点7: 防抖刷新
  void _debouncedRefresh() {
    _refreshDebouncer?.cancel();
    _refreshDebouncer = Timer(const Duration(seconds: 2), () {
      if (mounted) {
        refresh();
      }
    });
  }

  Future<void> refresh() async {
    _log.info('refresh...');
    await latestCachedRequest.refresh();
  }

  ListItem? get currentItem {
    if (latest == null || latest!.isEmpty) {
      return null;
    }

    final Set<String> completedIds = data.completedWorks.value.map((work) => work.id).toSet();

    for (final item in latest!) {
      final String itemId = item.id;
      if (!completedIds.contains(itemId)) {
        _log.info('Found current item: $itemId');
        return item;
      }
    }

    _log.info('All items in the latest list have been completed.');
    return null;
  }

  // ✅ 优化点8: 后台预加载
  void _preloadNextImages() {
    Future.microtask(() async {
      const int totalPreloadCount = 20;

      if (latest == null || latest!.isEmpty || latest!.length < minimumRemoteLoadCount) {
        _log.info('Preload failed: latest list is empty.');
        return;
      }

      final Set<String> completedIds = data.completedWorks.value.map((work) => work.id).toSet();
      int startIndex = -1;
      for (int i = 0; i < latest!.length; i++) {
        if (!completedIds.contains(latest![i].id)) {
          startIndex = i;
          break;
        }
      }

      if (startIndex == -1) {
        _log.info('Preload: All images completed, nothing to preload.');
        return;
      }

      final int endPreloadIndex = min(startIndex + totalPreloadCount, latest!.length);
      final List<ListItem> itemsToLoad = latest!.sublist(startIndex, endPreloadIndex);

      if (itemsToLoad.isEmpty) {
        _log.info('Preload: No items found in the range.');
        return;
      }

      final ListItem currentItemToLoad = itemsToLoad.removeAt(0);
      itemsToLoad.add(currentItemToLoad);

      _log.info('Preloading ${itemsToLoad.length} images. Current item: ${currentItemToLoad.id} will be loaded last.');

      int preloadCount = 0;
      for (final item in itemsToLoad) {
        if (item is RemoteItem) {
          try {
            ItemLoader.preload(item, device.suggestedQuality);
            await Future.delayed(const Duration(milliseconds: 100));
            preloadCount++;
          } catch (e) {
            _log.warning('Failed to load item for preloading: ${item.id}, error: $e');
          }
        }
      }

      _log.info('Preload initiated for $preloadCount remote images, current item was last.');
    });
  }

  // ✅ 优化点9: 缓存布局计算
  void _calculateLayout() {
    if (_layoutCalculated) return;

    final double availableHeight = device.screenSize.height - device.appBarHeight - device.bannerHeight - 120;
    final double paddedWidth = device.screenSize.width - 2 * 30;
    final double paddedHeight = availableHeight;
    final double targetWidth = paddedWidth;
    final double targetHeight = targetWidth * device.aspectRatio;

    if (targetHeight > paddedHeight) {
      _cachedCanvasHeight = paddedHeight;
      _cachedCanvasWidth = paddedHeight / device.aspectRatio;
    } else {
      _cachedCanvasWidth = targetWidth;
      _cachedCanvasHeight = targetHeight;
    }

    _layoutCalculated = true;
  }

  @override
  Widget build(BuildContext context) {
    if (isLoading) return scrollableDummy;

    _calculateLayout();

    return Scaffold(
      backgroundColor: SkinHelper.colorWhite,
      appBar: AppBar(
        backgroundColor: SkinHelper.colorWhite,
        centerTitle: true,
        leading: RepaintBoundary(
          key: _collectionKey,
          child: ScaleTransition(
            scale: _collectionAnimation,
            child: IconButton(
              onPressed: () {
                audio.playSfx(SfxType.click);
                Navigator.push(context, CollectionScreen.buildRoute());
              },
              icon: const Icon(Icons.collections, color: Colors.black87),
            ),
          ),
        ),
        title: SvgPicture.asset(
          'assets/images/title.svg',
          height: 32,
          placeholderBuilder: (BuildContext context) => const Text(
            'Jigsort Solitaire',
            style: TextStyle(color: Colors.black87, fontWeight: FontWeight.bold, fontSize: 24),
          ),
        ),
        // title: // Release模式下显示内存信息
        //     MemoryMonitor.getMemoryWidget(),
        actions: [
          IconButton(
            onPressed: () {
              audio.playSfx(SfxType.click);
              Navigator.push(context, SettingScreen.buildRoute());
            },
            icon: const Icon(Icons.settings, color: Colors.black87),
          ),
        ],
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Expanded(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 30),
                  child: SizedBox(
                    width: _cachedCanvasWidth!,
                    height: _cachedCanvasHeight!,
                    child: ValueListenableBuilder(
                      valueListenable: data.completedWorks,
                      builder: (context, value, child) {
                        return HomeBoardPlay(
                          key: _canvasKey,
                          canvasWidth: _cachedCanvasWidth!,
                          canvasHeight: _cachedCanvasHeight!,
                          collectionKey: _collectionKey,
                          onCollectionDone: () {
                            _log.info('onCollectionDone, 启动合集收纳反馈动画');
                            audio.playSfx(SfxType.appear);
                            _collectionController.forward(from: 0.0);
                          },
                        );
                      },
                    ),
                  ),
                ),
                playButton,
              ],
            ),
          ),
          SafeArea(
            child: SizedBox(
              height: context.read<Device>().bannerHeight,
              width: double.infinity,
              child: isBannerVisible ? getBanner('home_bottom') : const SizedBox.shrink(),
            ),
          ),
        ],
      ),
    );
  }

  // ✅ 优化点10: 导航状态管理
  void gotoPlay(ListItem item, {bool firstRun = false}) async {
    if (_isNavigating) {
      _log.info('Navigation already in progress, ignoring');
      return;
    }

    _log.info('goto play, firstRun = $firstRun');

    if (!mounted) return;

    _isNavigating = true;

    try {
      cleanBanner();

      if (!mounted) return;

      PageRouteBuilder? pageRouteBuilder = BoardPlay.buildRoute(item, firstRun: firstRun);
      final result = await Navigator.push(context, pageRouteBuilder);

      if (!mounted) return;

      // result 是 true， 说明关卡已经完成。 但此时可能播放插屏广告中， 需要等待用户关闭广告之后才能执行翻牌等逻辑
      if (result != null && result == true) {
        // 打印下当下的插屏广告状态
        _log.info('==================>interState =  $intersState');

        if (intersState == AdState.ready) {
          // 这种情况表示有插屏广告在播放，需要等待广告关闭之后才能执行翻牌动画等逻辑
          interPending = true;
          _log.info('Interstitial ad is currently playing, will execute post-ad logic after dismissal.');
          return;
        }

        _canvasKey.currentState?.startFlipAnimation();

        final bool hasSufficientData = latest != null && latest!.length >= minimumRemoteLoadCount;
        final bool isNetworkActive = latestCachedRequest.hasRecentSuccessfulFetch;

        if (hasSufficientData) {
          if (isNetworkActive) {
            _log.info('Game finished, data complete & Network Active. Triggering sequential preloading...');
            _preloadNextImages();
          } else {
            _log.info('Game finished, data complete but Network inactive. Attempting refresh.');
            refresh();
          }
        } else {
          _log.info('Game finished, remote data incomplete. Attempting refresh...');
          refresh();
        }
      }
    } finally {
      _isNavigating = false;
    }
  }

  Widget get playButton {
    return MyElevatedButton(
      width: device.isTablet ? 300 : 200,
      height: 70,
      borderRadius: BorderRadius.circular(20),
      gradient: LinearGradient(colors: [SkinHelper.coreBgColor, SkinHelper.slotBorderColor]),
      onPressed: () async {
        audio.playSfx(SfxType.click);
        if (currentItem != null) {
          gotoPlay(currentItem!);
        } else {
          Fluttertoast.showToast(
            msg: AppLocalizations.of(context)!.noMorePicture,
            toastLength: Toast.LENGTH_SHORT,
            gravity: ToastGravity.CENTER,
            timeInSecForIosWeb: 1,
            backgroundColor: SkinHelper.slotBorderColor,
            textColor: Colors.white,
            fontSize: 16.0,
          );
        }
      },
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            AppLocalizations.of(context)!.play,
            style: const TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
          ),
          Text('${AppLocalizations.of(context)!.level} ${data.currentLevel + 1}', style: const TextStyle(color: Colors.white, fontSize: 16)),
        ],
      ),
    );
  }

  Widget get scrollableDummy => Scaffold(
    backgroundColor: SkinHelper.colorWhite,
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          SizedBox(width: 40, height: 40, child: CircularProgressIndicator(strokeWidth: 3, valueColor: AlwaysStoppedAnimation<Color>(SkinHelper.coreBgColor))),
          const SizedBox(height: 20),
          Text(
            "Loading...",
            style: TextStyle(color: SkinHelper.slotBorderColor.withOpacity(0.7), fontSize: 14, fontWeight: FontWeight.w500),
          ),
        ],
      ),
    ),
  );

  ///////////////////////// 初始化相关 /////////////////////////

  static bool hasInit = false;

  void initThird() async {
    if (hasInit) return;
    hasInit = true;

    TrackingStatus attStatus = await AppTrackingTransparency.trackingAuthorizationStatus;
    if (attStatus == TrackingStatus.authorized && Platform.isIOS) {
      // ATT 通过之后，ios需要调用相关的原生sdk接口做进一步的初始化
    }
    initFCM();
    initAd();
    AdjustHelper.init(Persistence().uuid);

    final idfa = await AppTrackingTransparency.getAdvertisingIdentifier();
    _log.info("idfa: $idfa");
  }

  Future<bool> initATT() async {
    TrackingStatus status = await AppTrackingTransparency.trackingAuthorizationStatus;
    _log.info('initATT111 $status');
    if (status == TrackingStatus.notDetermined) {
      status = await AppTrackingTransparency.requestTrackingAuthorization();
      _log.info('initATT222 $status');
    }
    return status == TrackingStatus.authorized;
  }

  initAd() {
    _log.info('initAd');
    ApplovinAdsController applovinAdsController = context.read<ApplovinAdsController>();
    applovinAdsController.initialize();
  }

  initFCM() async {
    try {
      final fcmToken = await FirebaseMessaging.instance.getToken();
      _log.info("FCM Token: $fcmToken");

      FirebaseMessaging messaging = FirebaseMessaging.instance;
      NotificationSettings settings = await messaging.requestPermission(
        alert: true,
        announcement: false,
        badge: true,
        carPlay: false,
        criticalAlert: false,
        provisional: false,
        sound: true,
      );

      _log.warning('User granted permission: ${settings.authorizationStatus}');
    } catch (e) {
      FirebaseCrashlytics.instance.log("FCM FirebaseMessaging.instance.getToken error: $e");
      _log.warning(e);
    }
  }
}
