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

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_cache_manager/file.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:get/get.dart';
import 'package:pullex/pullex.dart';
import 'package:share_plus/share_plus.dart';

import 'package:f0ckapp/services/api.dart';
import 'package:f0ckapp/widgets/tagfooter.dart';
import 'package:f0ckapp/utils/animatedtransition.dart';
import 'package:f0ckapp/controller/authcontroller.dart';
import 'package:f0ckapp/widgets/favoritesection.dart';
import 'package:f0ckapp/screens/fullscreen.dart';
import 'package:f0ckapp/widgets/end_drawer.dart';
import 'package:f0ckapp/controller/settingscontroller.dart';
import 'package:f0ckapp/controller/mediacontroller.dart';
import 'package:f0ckapp/models/item.dart';
import 'package:f0ckapp/widgets/tagsection.dart';
import 'package:f0ckapp/widgets/video_widget.dart';

enum ShareAction { media, directLink, postLink }

class MediaDetailScreen extends StatefulWidget {
  final int initialId;
  const MediaDetailScreen({super.key, required this.initialId});

  @override
  State<MediaDetailScreen> createState() => _MediaDetailScreenState();
}

class _MediaDetailScreenState extends State<MediaDetailScreen> {
  PageController? _pageController;
  final MediaController mediaController = Get.find<MediaController>();
  final SettingsController settingsController = Get.find<SettingsController>();
  final AuthController authController = Get.find<AuthController>();
  final RxInt _currentIndex = 0.obs;
  final MethodChannel _mediaSaverChannel = const MethodChannel('MediaShit');
  final Map<int, PullexRefreshController> _refreshControllers = {};

  bool _isLoading = true;
  bool _itemNotFound = false;
  final Set<int> _readyItemIds = {};

  final List<PopupMenuEntry<ShareAction>> _shareMenuItems = const [
    PopupMenuItem(
      value: ShareAction.media,
      child: ListTile(leading: Icon(Icons.image), title: Text('Als Datei')),
    ),
    PopupMenuItem(
      value: ShareAction.directLink,
      child: ListTile(leading: Icon(Icons.link), title: Text('Link zur Datei')),
    ),
    PopupMenuItem(
      value: ShareAction.postLink,
      child: ListTile(
        leading: Icon(Icons.article),
        title: Text('Link zum f0ck'),
      ),
    ),
  ];

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

  Future<void> _loadInitialItem() async {
    int initialIndex = mediaController.items.indexWhere(
      (item) => item.id == widget.initialId,
    );

    if (initialIndex < 0) {
      await mediaController.fetchInitial(id: widget.initialId + 20);
      initialIndex = mediaController.items.indexWhere(
        (item) => item.id == widget.initialId,
      );
    }

    if (initialIndex < 0) {
      if (mounted) {
        setState(() {
          _itemNotFound = true;
          _isLoading = false;
        });
      }
      return;
    }

    if (mounted) {
      _currentIndex.value = initialIndex;
      _pageController = PageController(initialPage: initialIndex);
      if (mediaController.items[initialIndex].mime.startsWith('image/')) {
        _readyItemIds.add(mediaController.items[initialIndex].id);
      }
      setState(() => _isLoading = false);
    }
  }

  void _showMsg(String message) {
    if (!mounted) return;
    Get
      ..closeAllSnackbars()
      ..snackbar('hehe', message, snackPosition: SnackPosition.BOTTOM);
  }

  Future<void> _onRefresh(
    int itemId,
    PullexRefreshController controller,
  ) async {
    if (mediaController.loading.value) {
      controller.refreshCompleted();
      return;
    }

    try {
      final MediaItem item = await ApiService().fetchItemById(itemId);
      final int index = mediaController.items.indexWhere(
        (item) => item.id == itemId,
      );
      if (index != -1) {
        mediaController.items[index] = item;
        mediaController.items.refresh();
      }
      controller.refreshCompleted();
    } catch (e) {
      _showMsg('Fehler beim Aktualisieren: $e');
      controller.refreshFailed();
    }
  }

  void _onPageChanged(int idx) {
    if (idx != _currentIndex.value) {
      _currentIndex.value = idx;
      final MediaItem item = mediaController.items[idx];
      if (item.mime.startsWith('image/') && !_readyItemIds.contains(item.id)) {
        setState(() => _readyItemIds.add(item.id));
      }
    }
    if (idx >= mediaController.items.length - 2 &&
        !mediaController.loading.value &&
        !mediaController.atEnd.value) {
      mediaController.fetchMore();
    } else if (idx <= 1 &&
        !mediaController.loading.value &&
        !mediaController.atStart.value) {
      mediaController.fetchNewer();
    }
  }

  Future<void> _downloadMedia(MediaItem item) async {
    try {
      final File file = await DefaultCacheManager().getSingleFile(
        item.mediaUrl,
      );

      final bool? success = await _mediaSaverChannel.invokeMethod<bool>(
        'saveFile',
        {'filePath': file.path, 'fileName': item.dest},
      );

      success == true
          ? _showMsg('${item.dest} wurde in Downloads/fApp neigespeichert.')
          : _showMsg('${item.dest} konnte nicht heruntergeladen werden.');
    } catch (e) {
      _showMsg('Fehler beim Download: $e');
    }
  }

  Future<void> _handleShareAction(ShareAction value, MediaItem item) async {
    try {
      if (value == ShareAction.media) {
        final File file = await DefaultCacheManager().getSingleFile(
          item.mediaUrl,
        );
        final Uint8List bytes = await file.readAsBytes();
        final ShareParams params = ShareParams(
          files: [XFile.fromData(bytes, mimeType: item.mime)],
        );
        await SharePlus.instance.share(params);
        return;
      }

      final String textToShare;
      switch (value) {
        case ShareAction.directLink:
          textToShare = item.mediaUrl;
          break;
        case ShareAction.postLink:
          textToShare = item.postUrl;
          break;
        case ShareAction.media:
          return;
      }
      await SharePlus.instance.share(ShareParams(text: textToShare));
    } catch (e) {
      _showMsg('Fehler beim Teilen: $e');
    }
  }

  @override
  void dispose() {
    _pageController?.dispose();
    for (PullexRefreshController controller in _refreshControllers.values) {
      controller.dispose();
    }
    super.dispose();
  }

  Widget _buildMedia(MediaItem item, bool isActive) {
    if (item.mime.startsWith('image/')) {
      return CachedNetworkImage(
        imageUrl: item.mediaUrl,
        fit: BoxFit.contain,
        errorWidget: (c, e, s) => const Icon(Icons.broken_image, size: 100),
      );
    } else if (item.mime.startsWith('video/') ||
        item.mime.startsWith('audio/')) {
      return VideoWidget(
        details: item,
        isActive: isActive,
        onInitialized: () {
          if (mounted && !_readyItemIds.contains(item.id)) {
            setState(() => _readyItemIds.add(item.id));
          }
        },
      );
    } else {
      return const Icon(Icons.help_outline, size: 100);
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) {
      return Scaffold(
        appBar: AppBar(title: Text('Lade f0ck #${widget.initialId}...')),
        body: const Center(child: CircularProgressIndicator()),
      );
    }

    if (_itemNotFound) {
      return Scaffold(
        appBar: AppBar(title: const Text('Fehler')),
        body: const Center(child: Text('f0ck nicht gefunden.')),
      );
    }

    return Obx(() {
      if (mediaController.items.isEmpty ||
          _currentIndex.value >= mediaController.items.length) {
        return Scaffold(
          appBar: AppBar(title: const Text('Fehler')),
          body: const Center(child: Text('Keine Items zum Anzeigen.')),
        );
      }
      final MediaItem currentItem = mediaController.items[_currentIndex.value];
      return Scaffold(
        endDrawer: const EndDrawer(),
        endDrawerEnableOpenDragGesture:
            settingsController.drawerSwipeEnabled.value,
        appBar: AppBar(
          title: Text('f0ck #${currentItem.id}'),
          actions: [
            IconButton(
              icon: const Icon(Icons.fullscreen),
              onPressed: () {
                Get.to(
                  FullScreenMediaView(item: currentItem),
                  fullscreenDialog: true,
                );
              },
            ),
            IconButton(
              icon: const Icon(Icons.download),
              onPressed: () async => await _downloadMedia(currentItem),
            ),
            PopupMenuButton<ShareAction>(
              onSelected: (value) => _handleShareAction(value, currentItem),
              itemBuilder: (context) => _shareMenuItems,
              icon: const Icon(Icons.share),
            ),
            Builder(
              builder: (context) => IconButton(
                icon: const Icon(Icons.menu),
                onPressed: () => Scaffold.of(context).openEndDrawer(),
              ),
            ),
          ],
        ),
        body: PageView.builder(
          controller: _pageController!,
          itemCount: mediaController.items.length,
          onPageChanged: _onPageChanged,
          itemBuilder: (context, index) {
            final MediaItem item = mediaController.items[index];
            final bool isReady = _readyItemIds.contains(item.id);
            final ScrollController scrollController = ScrollController();
            final PullexRefreshController refreshController =
                _refreshControllers.putIfAbsent(
                  item.id,
                  () => PullexRefreshController(),
                );

            return PullexRefresh(
              onRefresh: () => _onRefresh(item.id, refreshController),
              header: const WaterDropHeader(),
              controller: refreshController,
              child: CustomScrollView(
                controller: scrollController,
                slivers: [
                  SliverToBoxAdapter(
                    child: AnimatedBuilder(
                      animation: _pageController!,
                      builder: (context, child) {
                        return buildAnimatedTransition(
                          context: context,
                          pageController: _pageController!,
                          index: index,
                          child: child!,
                        );
                      },
                      child: Obx(
                        () => _buildMedia(item, index == _currentIndex.value),
                      ),
                    ),
                  ),
                  if (isReady)
                    SliverToBoxAdapter(
                      child: GestureDetector(
                        onTap: () => settingsController.hideVideoControls(),
                        behavior: HitTestBehavior.translucent,
                        child: Padding(
                          padding: const EdgeInsets.all(16.0),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: [
                              TagSection(tags: item.tags ?? []),
                              Obx(
                                () => Visibility(
                                  visible: authController.isLoggedIn,
                                  child: Padding(
                                    padding: const EdgeInsets.only(top: 20.0),
                                    child: FavoriteSection(
                                      item: item,
                                      index: index,
                                    ),
                                  ),
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  const SliverToBoxAdapter(
                    child: SafeArea(child: SizedBox.shrink()),
                  ),
                ],
              ),
            );
          },
        ),
        persistentFooterButtons: mediaController.tag.value != null
            ? [TagFooter()]
            : null,
      );
    });
  }
}
