part of 'danmaku_panel_body.dart';

extension _DanmakuPanelBodyView on _DanmakuPanelBodyState {
  Widget? _buildEmptyState() {
    final state = widget.sessionState;
    if (state is DanmakuSessionIdle) {
      if (!widget.danmakuSourceConfigured) {
        return _emptyStatePage(
          icon: Icons.subtitles,
          title: '弹幕未配置',
          description: '请先在设置中配置弹幕数据源',
          actions: [
            if (widget.onGoToSettings != null)
              _emptyStateCta('前往设置', widget.onGoToSettings!),
          ],
        );
      }
      if (widget.danmakuGlobalEnabled) {
        return _emptyStatePage(
          icon: Icons.subtitles,
          title: '正在搜索弹幕…',
          showSpinner: true,
        );
      }
      return _emptyStatePage(
        icon: Icons.subtitles,
        title: '弹幕已关闭',
        description: '开启后将自动匹配弹幕',
        actions: [
          if (widget.onToggleDanmakuEnabled != null)
            _emptyStateCta('开启弹幕', widget.onToggleDanmakuEnabled!),
        ],
      );
    }
    if (state is DanmakuSessionMatching ||
        (state is DanmakuSessionMatched &&
            state.commentStatus == DanmakuCommentStatus.loading)) {
      return _emptyStatePage(
        icon: Icons.subtitles,
        title: '正在搜索弹幕…',
        showSpinner: true,
      );
    }
    if (state is DanmakuSessionEmpty) {
      return _emptyStatePage(
        icon: Icons.search_off,
        title: '未找到匹配弹幕',
        description: '可尝试手动搜索匹配',
        actions: [_emptyStateCta('搜索弹幕', widget.onOpenSearch)],
      );
    }
    if (state is DanmakuSessionFailed) {
      return _emptyStatePage(
        icon: Icons.error_outline,
        title: '加载失败',
        description: '弹幕匹配请求出错',
        actions: [
          if (widget.onRetry != null) _emptyStateCta('重试', widget.onRetry!),
          _emptyStateCta('搜索弹幕', widget.onOpenSearch),
        ],
      );
    }
    return null;
  }

  Widget _emptyStatePage({
    required IconData icon,
    required String title,
    String? description,
    List<Widget> actions = const [],
    bool showSpinner = false,
  }) {
    return SingleChildScrollView(
      child: Container(
        padding: const EdgeInsets.symmetric(vertical: 28, horizontal: 24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            if (showSpinner)
              Stack(
                alignment: Alignment.center,
                children: [
                  Icon(icon, color: const Color(0x61FFFFFF), size: 40),
                  const AppLoadingRing(size: 52, color: Color(0x99FFFFFF)),
                ],
              )
            else
              Icon(icon, color: const Color(0x61FFFFFF), size: 40),
            const SizedBox(height: 12),
            Text(
              title,
              style: const TextStyle(
                color: Colors.white70,
                fontSize: 14,
                fontWeight: FontWeight.w500,
              ),
            ),
            if (description != null) ...[
              const SizedBox(height: 4),
              Text(
                description,
                style: const TextStyle(color: Colors.white38, fontSize: 12),
                textAlign: TextAlign.center,
              ),
            ],
            if (actions.isNotEmpty) ...[
              const SizedBox(height: 16),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  for (var i = 0; i < actions.length; i++) ...[
                    if (i > 0) const SizedBox(width: 8),
                    actions[i],
                  ],
                ],
              ),
            ],
          ],
        ),
      ),
    );
  }

  Widget _emptyStateCta(String label, VoidCallback onTap) {
    return TextButton(
      onPressed: onTap,
      style: TextButton.styleFrom(
        foregroundColor: Colors.white,
        backgroundColor: Colors.white12,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      ),
      child: Text(label, style: const TextStyle(fontSize: 12)),
    );
  }

  Widget _buildMainMenu() {
    final hasMatch =
        widget.selectedMatchIndex >= 0 &&
        widget.selectedMatchIndex < widget.matches.length;
    final matchTitle = hasMatch
        ? widget.matches[widget.selectedMatchIndex].animeTitle
        : null;

    return SingleChildScrollView(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _sectionHeader('弹幕数据'),
          _menuItem(
            icon: Icons.search,
            label: '搜索弹幕',
            hasCheck: hasMatch,
            subtitle: matchTitle,
            onTap: widget.onOpenSearch,
          ),
          const FDivider(
            style: .delta(
              color: Color(0x1AFFFFFF),
              padding: .value(EdgeInsetsDirectional.only(start: 16)),
            ),
          ),
          _sectionHeader('操作'),
          _menuItem(
            icon: Icons.tune,
            label: '显示设置',
            onTap: () => _navigateTo(_DanmakuView.settings),
          ),
          _menuItem(
            icon: Icons.filter_alt_outlined,
            label: '过滤关键词',
            badge: widget.blockedKeywords.isNotEmpty
                ? '${widget.blockedKeywords.length}'
                : null,
            onTap: () => _navigateTo(_DanmakuView.filter),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: PanelToggleRow(
              label: '高能进度条',
              value: s.heatmapEnabled,
              onChanged: (v) => _emit(s.copyWith(heatmapEnabled: v)),
            ),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: PanelToggleRow(
              label: '弹幕',
              value: s.enabled,
              onChanged: (v) => _emit(s.copyWith(enabled: v)),
            ),
          ),
          const SizedBox(height: 4),
        ],
      ),
    );
  }

  Widget _sectionHeader(String title) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 10, 16, 4),
      child: Text(
        title,
        style: const TextStyle(
          color: Colors.white38,
          fontSize: 11,
          fontWeight: FontWeight.w500,
          letterSpacing: 0.4,
        ),
      ),
    );
  }

  Widget _menuItem({
    required IconData icon,
    required String label,
    String? subtitle,
    String? badge,
    bool hasCheck = false,
    bool showArrow = true,
    required VoidCallback onTap,
  }) {
    return InkWell(
      onTap: onTap,
      borderRadius: BorderRadius.circular(6),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
        child: Row(
          children: [
            if (hasCheck)
              const Icon(Icons.check, color: Colors.white70, size: 16)
            else
              Icon(icon, color: Colors.white54, size: 16),
            const SizedBox(width: 10),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    label,
                    style: const TextStyle(color: Colors.white, fontSize: 13),
                  ),
                  if (subtitle != null) ...[
                    const SizedBox(height: 1),
                    Text(
                      subtitle,
                      style: const TextStyle(
                        color: Colors.white38,
                        fontSize: 11,
                      ),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ],
                ],
              ),
            ),
            if (badge != null) ...[
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
                decoration: BoxDecoration(
                  color: Colors.white12,
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(
                  badge,
                  style: const TextStyle(color: Colors.white54, fontSize: 11),
                ),
              ),
              const SizedBox(width: 4),
            ],
            if (showArrow)
              const Icon(Icons.chevron_right, color: Colors.white24, size: 16),
          ],
        ),
      ),
    );
  }

  Widget _buildSettingsDrawer() {
    return PlayerDrawerPanel(
      title: '显示设置',
      onBack: _back,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          PanelToggleRow(
            label: '固定弹幕转滚动',
            value: s.fixedToScroll,
            onChanged: (v) => _emit(s.copyWith(fixedToScroll: v)),
          ),
          PanelStepperRow(
            label: '弹幕行数',
            display: s.maxRows == 0 ? '自动' : '${s.maxRows} 行',
            onDecrement: s.maxRows > 0
                ? () => _emit(s.copyWith(maxRows: s.maxRows - 1))
                : null,
            onIncrement: s.maxRows < 10
                ? () => _emit(s.copyWith(maxRows: s.maxRows + 1))
                : null,
          ),
          const FDivider(
            style: .delta(
              color: Color(0x1AFFFFFF),
              padding: .value(EdgeInsets.zero),
            ),
          ),
          const SizedBox(height: 6),
          PanelSliderRow(
            label: '延迟显示',
            value: s.offset,
            min: -10.0,
            max: 10.0,
            step: 0.5,
            display:
                '${s.offset >= 0 ? '+' : ''}${s.offset.toStringAsFixed(1)}s',
            onChanged: (v) => _emit(s.copyWith(offset: _round(v, -10.0, 10.0))),
          ),
          PanelSliderRow(
            label: '行间距',
            value: s.lineHeight,
            min: 1.0,
            max: 3.0,
            step: 0.1,
            display: s.lineHeight.toStringAsFixed(1),
            onChanged: (v) =>
                _emit(s.copyWith(lineHeight: _round(v, 1.0, 3.0))),
          ),
          PanelSliderRow(
            label: '基础速度',
            value: s.speed,
            min: 0.25,
            max: 2.0,
            step: 0.25,
            display: '${s.speed.toStringAsFixed(2)}x',
            onChanged: (v) => _emit(s.copyWith(speed: v.clamp(0.25, 2.0))),
          ),
          PanelSliderRow(
            label: '字号大小',
            value: s.fontSize,
            min: 12,
            max: 40,
            step: 2,
            display: s.fontSize.round().toString(),
            onChanged: (v) => _emit(s.copyWith(fontSize: _round(v, 12, 40))),
          ),
          PanelToggleRow(
            label: '粗体',
            value: s.bold,
            onChanged: (v) => _emit(s.copyWith(bold: v)),
          ),
          const FDivider(
            style: .delta(
              color: Color(0x1AFFFFFF),
              padding: .value(EdgeInsets.zero),
            ),
          ),
          const SizedBox(height: 6),
          PanelSliderRow(
            label: '不透明度',
            value: s.opacity,
            min: 0.1,
            max: 1.0,
            step: 0.1,
            display: '${(s.opacity * 100).round()}%',
            onChanged: (v) => _emit(s.copyWith(opacity: _round(v, 0.1, 1.0))),
          ),
          PanelSliderRow(
            label: '描边大小',
            value: s.strokeWidth,
            min: 0.0,
            max: 3.0,
            step: 0.5,
            display: s.strokeWidth.toStringAsFixed(1),
            onChanged: (v) =>
                _emit(s.copyWith(strokeWidth: _round(v, 0.0, 3.0))),
          ),
          const FDivider(
            style: .delta(
              color: Color(0x1AFFFFFF),
              padding: .value(EdgeInsets.zero),
            ),
          ),
          _fontFamilyRow(),
          const SizedBox(height: 8),
          _resetButton(),
          const SizedBox(height: 4),
        ],
      ),
    );
  }


  static double _round(double v, double min, double max) =>
      (v.clamp(min, max) * 10).round() / 10;

  static const _fontPresets = [
    (label: '系统默认', value: null),
    (label: 'PingFang SC', value: 'PingFang SC'),
    (label: 'Heiti SC', value: 'Heiti SC'),
    (label: 'Arial', value: 'Arial'),
  ];

  Widget _fontFamilyRow() {
    final current = s.fontFamily;
    final label =
        _fontPresets.where((p) => p.value == current).firstOrNull?.label ??
        '系统默认';
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 6),
      child: Row(
        children: [
          const Expanded(
            child: Text(
              '字体',
              style: TextStyle(color: Colors.white70, fontSize: 13),
            ),
          ),
          GestureDetector(
            onTap: _showFontPicker,
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  label,
                  style: const TextStyle(
                    color: Colors.lightBlueAccent,
                    fontSize: 13,
                  ),
                ),
                const SizedBox(width: 2),
                const Icon(
                  Icons.unfold_more,
                  color: Colors.lightBlueAccent,
                  size: 14,
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  void _showFontPicker() {
    showModalBottomSheet<void>(
      context: context,
      backgroundColor: const Color(0xFF252525),
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(14)),
      ),
      builder: (_) => Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Padding(
            padding: EdgeInsets.fromLTRB(20, 16, 20, 8),
            child: Text(
              '选择字体',
              style: TextStyle(
                color: Colors.white,
                fontSize: 15,
                fontWeight: FontWeight.w600,
              ),
            ),
          ),
          for (final p in _fontPresets)
            ListTile(
              title: Text(
                p.label,
                style: TextStyle(
                  color: Colors.white,
                  fontFamily: p.value,
                  fontSize: 14,
                ),
              ),
              trailing: s.fontFamily == p.value
                  ? const Icon(Icons.check, color: Colors.white70, size: 18)
                  : null,
              onTap: () {
                Navigator.pop(context);
                _emit(s.copyWith(fontFamily: p.value));
              },
            ),
          const SizedBox(height: 16),
        ],
      ),
    );
  }

  Widget _resetButton() {
    return SizedBox(
      width: double.infinity,
      child: TextButton(
        onPressed: () => _emit(defaultDanmakuPanelSettings()),
        style: TextButton.styleFrom(
          foregroundColor: Colors.white54,
          backgroundColor: Colors.white10,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
          padding: const EdgeInsets.symmetric(vertical: 10),
        ),
        child: const Text('重置', style: TextStyle(fontSize: 13)),
      ),
    );
  }

  Widget _buildFilterDrawer() {
    return PlayerDrawerPanel(
      title: '弹幕过滤',
      onBack: _back,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _keywordInput(),
          const SizedBox(height: 8),
          const FDivider(
            style: .delta(
              color: Color(0x1AFFFFFF),
              padding: .value(EdgeInsets.zero),
            ),
          ),
          const SizedBox(height: 4),
          _keywordList(),
          const SizedBox(height: 4),
        ],
      ),
    );
  }

  Widget _keywordInput() {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white.withValues(alpha: 0.05),
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: Colors.white12),
      ),
      child: Row(
        children: [
          const Padding(
            padding: EdgeInsets.only(left: 10),
            child: Icon(
              Icons.filter_alt_outlined,
              color: Colors.white38,
              size: 16,
            ),
          ),
          Expanded(
            child: TextField(
              controller: _keywordController,
              style: const TextStyle(color: Colors.white, fontSize: 13),
              decoration: const InputDecoration(
                hintText: '输入要过滤的关键词',
                hintStyle: TextStyle(color: Colors.white38, fontSize: 13),
                border: InputBorder.none,
                contentPadding: EdgeInsets.symmetric(
                  horizontal: 10,
                  vertical: 10,
                ),
                isDense: true,
              ),
              onSubmitted: _addKeyword,
              inputFormatters: [LengthLimitingTextInputFormatter(30)],
            ),
          ),
          IconButton(
            icon: const Icon(Icons.add_circle_outline, size: 18),
            color: Colors.white54,
            padding: const EdgeInsets.only(right: 8),
            constraints: const BoxConstraints(minWidth: 32, minHeight: 32),
            onPressed: () => _addKeyword(_keywordController.text),
          ),
        ],
      ),
    );
  }

  void _addKeyword(String raw) {
    final kw = raw.trim();
    if (kw.isEmpty) return;
    if (widget.blockedKeywords.contains(kw)) {
      _keywordController.clear();
      return;
    }
    widget.onAddKeyword(kw);
    _keywordController.clear();
  }

  Widget _keywordList() {
    final keywords = widget.blockedKeywords;
    if (keywords.isEmpty) {
      return const Padding(
        padding: EdgeInsets.symmetric(vertical: 12),
        child: Center(
          child: Text(
            '暂无屏蔽关键词',
            style: TextStyle(color: Colors.white38, fontSize: 12),
          ),
        ),
      );
    }
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        for (final kw in keywords)
          Padding(
            padding: const EdgeInsets.only(bottom: 4),
            child: Row(
              children: [
                const Icon(
                  Icons.label_outline,
                  color: Colors.white38,
                  size: 14,
                ),
                const SizedBox(width: 8),
                Expanded(
                  child: Text(
                    kw,
                    style: const TextStyle(color: Colors.white70, fontSize: 13),
                  ),
                ),
                IconButton(
                  icon: const Icon(Icons.close, size: 14),
                  color: Colors.white38,
                  padding: EdgeInsets.zero,
                  constraints: const BoxConstraints(
                    minWidth: 28,
                    minHeight: 28,
                  ),
                  onPressed: () => widget.onRemoveKeyword(kw),
                ),
              ],
            ),
          ),
      ],
    );
  }

  Widget _buildSearchDrawer() {
    return PlayerDrawerPanel(
      title: '搜索弹幕',
      onBack: _back,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          _matchesContent(),
          const SizedBox(height: 8),
          _manualSearchTrigger(),
          const SizedBox(height: 4),
        ],
      ),
    );
  }

  Widget _matchesContent() {
    if (widget.isLoading) {
      return const Padding(
        padding: EdgeInsets.symmetric(vertical: 16),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AppLoadingRing(size: 14, color: Colors.white54),
            SizedBox(width: 8),
            Text(
              '正在匹配弹幕源…',
              style: TextStyle(color: Colors.white54, fontSize: 12),
            ),
          ],
        ),
      );
    }

    final matches = widget.matches;
    if (matches.isEmpty) {
      return const Padding(
        padding: EdgeInsets.symmetric(vertical: 12),
        child: Row(
          children: [
            Icon(Icons.info_outline, color: Colors.white24, size: 14),
            SizedBox(width: 6),
            Expanded(
              child: Text(
                '未匹配到弹幕源，可手动搜索',
                style: TextStyle(color: Colors.white38, fontSize: 12),
              ),
            ),
          ],
        ),
      );
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.only(bottom: 6),
          child: Text(
            '弹幕源 (${matches.length} 条)',
            style: const TextStyle(color: Colors.white38, fontSize: 11),
          ),
        ),
        ...List.generate(matches.length, (i) {
          final m = matches[i];
          final selected = i == widget.selectedMatchIndex;
          return DanmakuMatchTile(
            candidate: m,
            selected: selected,
            onTap: () => widget.onMatchSelected(i),
          );
        }),
      ],
    );
  }

  Widget _manualSearchTrigger() {
    return SizedBox(
      width: double.infinity,
      height: 40,
      child: OutlinedButton.icon(
        onPressed: widget.onOpenSearch,
        style: OutlinedButton.styleFrom(
          alignment: Alignment.centerLeft,
          foregroundColor: Colors.white,
          side: const BorderSide(color: Color(0x664FA8FF)),
          backgroundColor: const Color(0x10FFFFFF),
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
          padding: const EdgeInsets.symmetric(horizontal: 12),
        ),
        icon: const Icon(Icons.manage_search, size: 16),
        label: const Row(
          children: [
            Expanded(
              child: Text(
                '搜索并手动选择分集',
                style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
              ),
            ),
            Icon(Icons.chevron_right, size: 14, color: Colors.white38),
          ],
        ),
      ),
    );
  }
}
