part of '../media_detail_screen.dart';

extension _MediaDetailActionButtons on _MediaDetailScreenState {
  Widget _buildActionButtons(MediaItem metadata) {
    final isTv = PlatformDetector.isTV();
    final tvScale = TvLayoutConstants.scaleOf(context);
    final actionSize = isTv ? _tvDetailActionSize * tvScale : 48.0;
    final playButtonLabel = _getPlayButtonLabel(metadata);
    final playButtonIcon = AppIcon(_getPlayButtonIcon(metadata), fill: 1, size: isTv ? 22 * tvScale : 20);

    Future<void> onPlayPressed() async {
      // For TV shows, play the OnDeck episode if available
      // Otherwise, play the first episode of the first season
      if (metadata.isShow) {
        if (_onDeckEpisode != null) {
          appLogger.d('Playing on deck episode: ${_onDeckEpisode!.title}');
          await navigateToVideoPlayerWithRefresh(
            context,
            metadata: _onDeckEpisode!,
            isOffline: widget.isOffline,
            onRefresh: _loadFullMetadata,
          );
        } else {
          // No on deck episode, fetch first episode of first season
          await _playFirstEpisode();
        }
      } else if (metadata.isSeason) {
        // For seasons, play the first episode
        if (_episodes.isNotEmpty) {
          await navigateToVideoPlayerWithRefresh(
            context,
            metadata: _episodes.first,
            isOffline: widget.isOffline,
            onRefresh: _loadFullMetadata,
          );
        } else {
          await _playFirstEpisode();
        }
      } else {
        appLogger.d('Playing: ${metadata.title}');
        // For movies or episodes, play directly
        await navigateToVideoPlayerWithRefresh(
          context,
          metadata: metadata,
          isOffline: widget.isOffline,
          onRefresh: _loadFullMetadata,
        );
      }
    }

    final primaryTrailer = _getPrimaryTrailer();

    final isKeyboardMode = InputModeTracker.isKeyboardMode(context);
    final colorScheme = Theme.of(context).colorScheme;

    // In keyboard/d-pad mode, focused buttons get a prominent style.
    // overlayColor is set to transparent to prevent the Material focus
    // overlay from dimming the background color we set.
    final focusBg = colorScheme.inverseSurface;
    final focusFg = colorScheme.onInverseSurface;
    final tonalBg = colorScheme.secondaryContainer;
    final idleBg = isTv ? tonalBg.withValues(alpha: 0.38) : tonalBg;
    final tonalFg = colorScheme.onSecondaryContainer;
    final noOverlay = WidgetStateProperty.resolveWith((states) {
      if (states.contains(WidgetState.focused)) return Colors.transparent;
      return null; // default for other states
    });

    ButtonStyle actionButtonStyle({Color? foregroundColor, EdgeInsetsGeometry? padding}) {
      if (!isKeyboardMode && !isTv) {
        if (padding != null) {
          return FilledButton.styleFrom(padding: padding);
        }
        return IconButton.styleFrom(
          minimumSize: const Size(48, 48),
          maximumSize: const Size(48, 48),
          foregroundColor: foregroundColor,
        );
      }
      return ButtonStyle(
        padding: padding != null ? WidgetStatePropertyAll(padding) : null,
        minimumSize: WidgetStatePropertyAll(padding == null ? Size.square(actionSize) : Size(0, actionSize)),
        maximumSize: padding == null ? WidgetStatePropertyAll(Size.square(actionSize)) : null,
        fixedSize: padding == null ? WidgetStatePropertyAll(Size.square(actionSize)) : null,
        tapTargetSize: MaterialTapTargetSize.shrinkWrap,
        visualDensity: VisualDensity.compact,
        overlayColor: noOverlay,
        backgroundColor: WidgetStateProperty.resolveWith((states) {
          if (states.contains(WidgetState.focused)) return focusBg;
          return idleBg;
        }),
        foregroundColor: WidgetStateProperty.resolveWith((states) {
          if (states.contains(WidgetState.focused)) return focusFg;
          return foregroundColor ?? tonalFg;
        }),
      );
    }

    return Focus(
      skipTraversal: true,
      onKeyEvent: _handlePlayButtonKeyEvent,
      child: Row(
        children: [
          SizedBox(
            height: actionSize,
            child: FilledButton(
              focusNode: _playButtonFocusNode,
              autofocus: isKeyboardMode,
              onPressed: onPlayPressed,
              style: actionButtonStyle(
                padding: EdgeInsets.symmetric(horizontal: isTv ? 17 * tvScale : 16, vertical: isTv ? 9 * tvScale : 0),
              ),
              child: playButtonLabel.isNotEmpty
                  ? Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        playButtonIcon,
                        SizedBox(width: isTv ? 7 * tvScale : 8),
                        Text(
                          playButtonLabel,
                          style: TextStyle(fontSize: isTv ? 17 * tvScale : 16, fontWeight: FontWeight.w700),
                        ),
                      ],
                    )
                  : playButtonIcon,
            ),
          ),
          SizedBox(width: isTv ? 8 * tvScale : 12),
          // Trailer button (only if trailer is available)
          if (primaryTrailer != null) ...[
            IconButton.filledTonal(
              onPressed: () async {
                await navigateToVideoPlayer(context, metadata: primaryTrailer);
              },
              icon: const AppIcon(Symbols.theaters_rounded, fill: 1),
              tooltip: t.tooltips.playTrailer,
              iconSize: isTv ? 21 * tvScale : 20,
              style: actionButtonStyle(),
            ),
            SizedBox(width: isTv ? 8 * tvScale : 12),
          ],
          // Shuffle button (only for shows and seasons)
          if (metadata.isShow || metadata.isSeason) ...[
            IconButton.filledTonal(
              onPressed: () async {
                await _handleShufflePlayWithQueue(context, metadata);
              },
              icon: const AppIcon(Symbols.shuffle_rounded, fill: 1),
              tooltip: t.tooltips.shufflePlay,
              iconSize: isTv ? 21 * tvScale : 20,
              style: actionButtonStyle(),
            ),
            SizedBox(width: isTv ? 8 * tvScale : 12),
          ],
          // Download button (hide in offline mode - already downloaded,
          // and on Apple TV where there's no user file storage).
          if (!widget.isOffline && !PlatformDetector.isAppleTV())
            _buildDownloadButton(metadata, actionButtonStyle, tvScale),
          SizedBox(width: isTv ? 8 * tvScale : 12),
          // Mark as watched/unwatched toggle (works offline too)
          _buildWatchedToggleButton(metadata, actionButtonStyle, tvScale),
          // Three-dots menu button (hidden in offline mode)
          if (!widget.isOffline) ...[
            SizedBox(width: isTv ? 8 * tvScale : 12),
            _buildMoreActionsButton(metadata, actionButtonStyle, tvScale),
          ],
        ],
      ),
    );
  }

  Widget _buildWatchedToggleButton(
    MediaItem metadata,
    ButtonStyle Function({Color? foregroundColor, EdgeInsetsGeometry? padding}) actionButtonStyle,
    double tvScale,
  ) {
    return IconButton.filledTonal(
      onPressed: () async {
        try {
          final isWatched = metadata.isWatched;
          if (widget.isOffline) {
            // Offline mode: queue action for later sync
            final offlineWatch = context.read<OfflineWatchProvider>();
            if (isWatched) {
              await offlineWatch.markAsUnwatched(serverId: metadata.serverId!, itemId: metadata.id);
            } else {
              await offlineWatch.markAsWatched(serverId: metadata.serverId!, itemId: metadata.id);
            }
            if (mounted) {
              showAppSnackBar(
                context,
                isWatched ? t.messages.markedAsUnwatchedOffline : t.messages.markedAsWatchedOffline,
              );
            }
          } else {
            // Online mode: dispatch via the right backend's neutral method so
            // Jellyfin items hit /UserPlayedItems and Plex items hit /:/scrobble.
            final serverId = metadata.serverId;
            if (serverId == null) return;
            final client = context.tryGetMediaClientForServer(serverId);
            if (client == null) return;

            if (isWatched) {
              await client.markUnwatched(metadata);
            } else {
              await client.markWatched(metadata);
            }
            if (mounted) {
              _watchStateChanged = true;
              showSuccessSnackBar(context, isWatched ? t.messages.markedAsUnwatched : t.messages.markedAsWatched);
            }
          }
        } catch (e) {
          if (mounted) {
            showErrorSnackBar(context, t.messages.errorLoading(error: e.toString()));
          }
        }
      },
      icon: AppIcon(metadata.isWatched ? Symbols.remove_done_rounded : Symbols.check_rounded, fill: 1),
      tooltip: metadata.isWatched ? t.tooltips.markAsUnwatched : t.tooltips.markAsWatched,
      iconSize: PlatformDetector.isTV() ? 21 * tvScale : 20,
      style: actionButtonStyle(),
    );
  }

  Widget _buildMoreActionsButton(
    MediaItem metadata,
    ButtonStyle Function({Color? foregroundColor, EdgeInsetsGeometry? padding}) actionButtonStyle,
    double tvScale,
  ) {
    return MediaContextMenu(
      key: _contextMenuKey,
      item: metadata,
      onRefresh: (_) => _loadFullMetadata(),
      child: Builder(
        builder: (buttonContext) => IconButton.filledTonal(
          onPressed: () {
            final renderBox = buttonContext.findRenderObject() as RenderBox?;
            if (renderBox != null) {
              final position = renderBox.localToGlobal(renderBox.size.center(Offset.zero));
              _contextMenuKey.currentState?.showContextMenu(buttonContext, position: position);
            }
          },
          icon: const AppIcon(Symbols.more_vert_rounded, fill: 1),
          iconSize: PlatformDetector.isTV() ? 21 * tvScale : 20,
          style: actionButtonStyle(),
        ),
      ),
    );
  }

  Widget _buildDownloadButton(
    MediaItem metadata,
    ButtonStyle Function({Color? foregroundColor, EdgeInsetsGeometry? padding}) actionButtonStyle,
    double tvScale,
  ) {
    return Consumer<DownloadProvider>(
      builder: (context, downloadProvider, _) {
        final iconSize = PlatformDetector.isTV() ? 21.0 * tvScale : 20.0;
        final globalKey = metadata.globalKey;
        final ruleKey = _syncRuleKeyForMetadata(context, downloadProvider, metadata);
        final progress = downloadProvider.getProgress(globalKey);
        final isQueueing = downloadProvider.isQueueing(globalKey);

        // Debug logging
        if (progress != null) {
          appLogger.d('UI rebuilding for $globalKey: status=${progress.status}, progress=${progress.progress}%');
        }

        // State 1: Queueing (building download queue)
        if (isQueueing) {
          return IconButton.filledTonal(
            onPressed: null,
            icon: LoadingIndicatorBox(size: iconSize),
            iconSize: iconSize,
            style: actionButtonStyle(),
          );
        }

        // State 2: Queued (waiting to download)
        if (progress?.status == DownloadStatus.queued) {
          final currentFile = progress?.currentFile;
          final tooltip = currentFile != null && currentFile.contains('episodes')
              ? t.downloads.queuedFilesTooltip(files: currentFile)
              : t.downloads.queuedTooltip;

          return IconButton.filledTonal(
            onPressed: null,
            tooltip: tooltip,
            icon: const AppIcon(Symbols.schedule_rounded, fill: 1),
            iconSize: iconSize,
            style: actionButtonStyle(),
          );
        }

        // State 3: Downloading (active download)
        if (progress?.status == DownloadStatus.downloading) {
          // Show episode count in tooltip for shows/seasons
          final currentFile = progress?.currentFile;
          final tooltip = currentFile != null && currentFile.contains('episodes')
              ? t.downloads.downloadingFilesTooltip(files: currentFile)
              : t.downloads.downloadingTooltip;

          return IconButton.filledTonal(
            onPressed: null,
            tooltip: tooltip,
            icon: _buildRadialProgress(progress?.progressPercent),
            iconSize: iconSize,
            style: actionButtonStyle(),
          );
        }

        // State 4: Paused (can resume)
        if (progress?.status == DownloadStatus.paused) {
          return IconButton.filledTonal(
            onPressed: () async {
              final client = _getMediaClientForMetadata(context);
              if (client == null) return;
              await downloadProvider.resumeDownload(globalKey, client);
              if (context.mounted) {
                showAppSnackBar(context, 'Download resumed');
              }
            },
            icon: const AppIcon(Symbols.pause_circle_outline_rounded, fill: 1),
            tooltip: 'Resume download',
            iconSize: iconSize,
            style: actionButtonStyle(foregroundColor: Colors.amber),
          );
        }

        // State 5: Failed (can retry)
        if (progress?.status == DownloadStatus.failed) {
          return IconButton.filledTonal(
            onPressed: () async {
              final client = _getMediaClientForMetadata(context);
              if (client == null) return;

              final versionConfig = await _resolveDownloadVersion(context, metadata, client);
              if (versionConfig == null || !context.mounted) return;

              await downloadProvider.deleteDownload(globalKey);
              try {
                await downloadProvider.queueDownload(metadata, client, versionConfig: versionConfig);

                if (context.mounted) {
                  showSuccessSnackBar(context, t.downloads.downloadQueued);
                }
              } on CellularDownloadBlockedException {
                if (context.mounted) {
                  showErrorSnackBar(context, t.settings.cellularDownloadBlocked);
                }
              }
            },
            icon: const AppIcon(Symbols.error_outline_rounded, fill: 1),
            tooltip: 'Retry download',
            iconSize: iconSize,
            style: actionButtonStyle(foregroundColor: Colors.red),
          );
        }

        // State 6: Cancelled (can delete or retry)
        if (progress?.status == DownloadStatus.cancelled) {
          return IconButton.filledTonal(
            onPressed: () async {
              // Show options: Delete or Retry
              final retry = await showConfirmDialog(
                context,
                title: 'Cancelled Download',
                message: 'This download was cancelled. What would you like to do?',
                cancelText: t.common.delete,
                confirmText: 'Retry',
              );

              if (!retry && context.mounted) {
                await downloadProvider.deleteDownload(globalKey);
                if (context.mounted) {
                  showSuccessSnackBar(context, t.downloads.downloadDeleted);
                }
              } else if (retry && context.mounted) {
                final client = _getMediaClientForMetadata(context);
                if (client == null) return;

                final versionConfig = await _resolveDownloadVersion(context, metadata, client);
                if (versionConfig == null || !context.mounted) return;

                await downloadProvider.deleteDownload(globalKey);
                try {
                  await downloadProvider.queueDownload(metadata, client, versionConfig: versionConfig);
                  if (context.mounted) {
                    showSuccessSnackBar(context, t.downloads.downloadQueued);
                  }
                } on CellularDownloadBlockedException {
                  if (context.mounted) {
                    showErrorSnackBar(context, t.settings.cellularDownloadBlocked);
                  }
                }
              }
            },
            icon: const AppIcon(Symbols.cancel_rounded, fill: 1),
            tooltip: 'Cancelled download',
            iconSize: iconSize,
            style: actionButtonStyle(foregroundColor: Colors.grey),
          );
        }

        // State 7: Partial Download (some episodes downloaded, not all)
        if (progress?.status == DownloadStatus.partial) {
          final hasSyncRule = downloadProvider.hasSyncRule(ruleKey);
          final currentFile = progress?.currentFile;

          if (hasSyncRule) {
            // Synced partial — this is the normal state for sync rules
            final syncRule = downloadProvider.getSyncRule(ruleKey);
            final isEnabled = syncRule?.enabled ?? true;
            final tooltip = currentFile != null
                ? '$currentFile (syncing ${t.downloads.keepNUnwatched(count: syncRule?.episodeCount.toString() ?? '?')})'
                : t.downloads.keepSynced;

            return IconButton.filledTonal(
              onPressed: () => _showSyncRuleActions(
                context,
                downloadProvider,
                metadata,
                ruleKey: ruleKey,
                downloadGlobalKey: globalKey,
              ),
              tooltip: tooltip,
              icon: AppIcon(isEnabled ? Symbols.sync_rounded : Symbols.sync_disabled_rounded, fill: 1),
              iconSize: iconSize,
              style: actionButtonStyle(foregroundColor: isEnabled ? Colors.teal : Colors.grey),
            );
          }

          final tooltip = currentFile != null
              ? 'Downloaded $currentFile - Click to complete'
              : 'Partially downloaded - Click to complete';

          return IconButton.filledTonal(
            onPressed: () async {
              final client = _getMediaClientForMetadata(context);
              if (client == null) return;

              final versionConfig = await _resolveDownloadVersion(context, metadata, client);
              if (versionConfig == null || !context.mounted) return;

              final count = await downloadProvider.queueMissingEpisodes(metadata, client, versionConfig: versionConfig);

              if (context.mounted) {
                final message = count > 0
                    ? t.downloads.episodesQueued(count: count)
                    : 'All episodes already downloaded';
                showAppSnackBar(context, message);
              }
            },
            tooltip: tooltip,
            icon: const AppIcon(Symbols.downloading_rounded, fill: 1),
            iconSize: iconSize,
            style: actionButtonStyle(foregroundColor: Colors.orange),
          );
        }

        // State 8: Downloaded/Completed (can delete)
        if (downloadProvider.isDownloaded(globalKey)) {
          final hasSyncRule = downloadProvider.hasSyncRule(ruleKey);

          if (hasSyncRule) {
            // Synced + complete — show sync icon
            final syncRule = downloadProvider.getSyncRule(ruleKey);
            final isEnabled = syncRule?.enabled ?? true;
            return IconButton.filledTonal(
              onPressed: () => _showSyncRuleActions(
                context,
                downloadProvider,
                metadata,
                ruleKey: ruleKey,
                downloadGlobalKey: globalKey,
              ),
              icon: AppIcon(isEnabled ? Symbols.sync_rounded : Symbols.sync_disabled_rounded, fill: 1),
              tooltip: t.downloads.keepNUnwatched(count: syncRule?.episodeCount.toString() ?? '?'),
              iconSize: iconSize,
              style: actionButtonStyle(foregroundColor: isEnabled ? Colors.teal : Colors.grey),
            );
          }

          return IconButton.filledTonal(
            onPressed: () async {
              // Show delete download confirmation
              final confirmed = await showDeleteConfirmation(
                context,
                title: t.downloads.deleteDownload,
                message: t.downloads.deleteConfirm(title: metadata.displayTitle),
              );

              if (confirmed && context.mounted) {
                await downloadProvider.deleteDownload(globalKey);
                if (context.mounted) {
                  showSuccessSnackBar(context, t.downloads.downloadDeleted);
                }
              }
            },
            icon: const AppIcon(Symbols.file_download_done_rounded, fill: 1),
            tooltip: t.downloads.deleteDownload,
            iconSize: iconSize,
            style: actionButtonStyle(foregroundColor: Colors.green),
          );
        }

        // State 9: Not downloaded (default - can download)
        return IconButton.filledTonal(
          onPressed: () async {
            final client = _getMediaClientForMetadata(context);
            if (client == null) return;

            try {
              final result = await showDownloadOptionsAndQueue(
                context,
                metadata: metadata,
                client: client,
                downloadProvider: downloadProvider,
              );
              if (result == null || !context.mounted) return;

              showSuccessSnackBar(context, result.toSnackBarMessage());
            } on CellularDownloadBlockedException {
              if (context.mounted) {
                showErrorSnackBar(context, t.settings.cellularDownloadBlocked);
              }
            }
          },
          icon: const AppIcon(Symbols.download_rounded, fill: 1),
          tooltip: t.downloads.downloadNow,
          iconSize: iconSize,
          style: actionButtonStyle(),
        );
      },
    );
  }
}
