part of 'danmaku_search_dialog.dart';

extension _DanmakuSearchDialogView on _DanmakuSearchDialogState {
  Widget _slideFade(Widget child, Animation<double> animation) {
    final curved = CurvedAnimation(
      parent: animation,
      curve: Curves.easeOutCubic,
      reverseCurve: Curves.easeInCubic,
    );
    return FadeTransition(
      opacity: curved,
      child: SlideTransition(
        position: Tween<Offset>(
          begin: _transitionOffset,
          end: Offset.zero,
        ).animate(curved),
        child: child,
      ),
    );
  }

  Widget _buildHeader() {
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 12, 8, 10),
      child: Row(
        children: [
          const Icon(Icons.search, color: Colors.white, size: 20),
          const SizedBox(width: 8),
          const Text(
            '搜索弹幕源',
            style: TextStyle(
              color: Colors.white,
              fontSize: 16,
              fontWeight: FontWeight.w600,
            ),
          ),
          const Spacer(),
          IconButton(
            iconSize: 18,
            visualDensity: VisualDensity.compact,
            onPressed: _dismiss,
            icon: const Icon(Icons.close, color: Colors.white70),
            tooltip: '关闭',
          ),
        ],
      ),
    );
  }

  Widget _buildSearchField() {
    return SizedBox(
      height: 44,
      child: TextField(
        controller: _queryCtrl,
        focusNode: _focusNode,
        autofocus: true,
        enabled: !_busy,
        style: const TextStyle(color: Colors.white, fontSize: 13),
        cursorColor: Colors.lightBlueAccent,
        textInputAction: TextInputAction.search,
        decoration: InputDecoration(
          filled: true,
          fillColor: Colors.white.withValues(alpha: 0.08),
          hintText: '输入番剧名后按 Enter 搜索',
          hintStyle: const TextStyle(color: Colors.white38, fontSize: 13),
          prefixIcon: const Icon(Icons.search, color: Colors.white54, size: 18),
          suffixIcon: IconButton(
            onPressed: _busy ? null : _submit,
            icon: const Icon(Icons.arrow_forward, size: 18),
            color: Colors.white70,
            tooltip: '搜索',
          ),
          contentPadding: const EdgeInsets.symmetric(
            horizontal: 12,
            vertical: 0,
          ),
          enabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(10),
            borderSide: const BorderSide(color: _kDivider),
          ),
          disabledBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(10),
            borderSide: const BorderSide(color: _kDivider),
          ),
          focusedBorder: OutlineInputBorder(
            borderRadius: BorderRadius.circular(10),
            borderSide: const BorderSide(color: _kAccent),
          ),
        ),
        onSubmitted: (_) => _submit(),
      ),
    );
  }

  Widget _buildBody() {
    switch (_phase) {
      case _Phase.idle:
        return _buildStateBody(
          key: const ValueKey('idle'),
          icon: Icons.search,
          title: '输入番剧名，按 Enter 搜索',
          subtitle: '可手动选择具体集数',
          showMessage: true,
        );
      case _Phase.searching:
        return _buildLoadingBody(
          key: const ValueKey('searching'),
          text: '正在搜索…',
        );
      case _Phase.results:
        return _buildResultsBody(
          key: const ValueKey('results'),
          disabled: false,
        );
      case _Phase.empty:
        return _buildStateBody(
          key: const ValueKey('empty'),
          icon: Icons.search_off,
          title: '未找到匹配的弹幕源',
          subtitle: '换个剧名试试',
        );
      case _Phase.error:
        return _buildStateBody(
          key: const ValueKey('error'),
          icon: Icons.error_outline,
          title: _messageText ?? '搜索失败',
          subtitle: '请检查弹幕服务地址',
        );
      case _Phase.episodesLoading:
        return _buildEpisodesLoadingBody();
      case _Phase.episodes:
        return _buildEpisodesBody(
          key: const ValueKey('episodes'),
          disabled: false,
        );
      case _Phase.applying:
        return _buildApplyingBody();
    }
  }

  Widget _buildStateBody({
    required Key key,
    required IconData icon,
    required String title,
    String? subtitle,
    bool showMessage = false,
  }) {
    return Center(
      key: key,
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 280),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(icon, color: Colors.white24, size: 32),
            const SizedBox(height: 12),
            Text(
              title,
              textAlign: TextAlign.center,
              style: const TextStyle(
                color: Colors.white70,
                fontSize: 13,
                fontWeight: FontWeight.w500,
              ),
            ),
            if (subtitle != null) ...[
              const SizedBox(height: 6),
              Text(
                subtitle,
                textAlign: TextAlign.center,
                style: const TextStyle(color: Colors.white54, fontSize: 12),
              ),
            ],
            if (showMessage && _messageText != null) ...[
              const SizedBox(height: 16),
              _buildMessageBanner(),
            ],
          ],
        ),
      ),
    );
  }

  Widget _buildLoadingBody({required Key key, required String text}) {
    return Center(
      key: key,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const AppLoadingRing(size: 22, color: Colors.white),
          const SizedBox(height: 12),
          Text(
            text,
            style: const TextStyle(color: Colors.white54, fontSize: 12),
          ),
        ],
      ),
    );
  }

  Widget _buildResultsBody({required Key key, required bool disabled}) {
    return Column(
      key: key,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          '搜索结果 ${_results.length} 条',
          style: const TextStyle(
            color: Colors.white70,
            fontSize: 14,
            fontWeight: FontWeight.w600,
          ),
        ),
        if (_messageText != null) ...[
          const SizedBox(height: 12),
          _buildMessageBanner(),
        ],
        const SizedBox(height: 12),
        Expanded(
          child: ListView.separated(
            padding: EdgeInsets.zero,
            itemCount: _results.length,
            separatorBuilder: (_, _) => const SizedBox(height: 8),
            itemBuilder: (_, i) => _buildResultTile(_results[i], disabled),
          ),
        ),
      ],
    );
  }

  Widget _buildEpisodesLoadingBody() {
    return Column(
      key: const ValueKey('episodes-loading'),
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _buildEpisodesHeader(disabled: false),
        const SizedBox(height: 16),
        const Expanded(
          child: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                AppLoadingRing(size: 22, color: Colors.white),
                SizedBox(height: 12),
                Text(
                  '正在加载分集…',
                  style: TextStyle(color: Colors.white54, fontSize: 12),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildEpisodesBody({
    required Key key,
    required bool disabled,
    bool useScrollController = true,
  }) {
    return Column(
      key: key,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _buildEpisodesHeader(disabled: disabled),
        if (_messageText != null) ...[
          const SizedBox(height: 12),
          _buildMessageBanner(),
        ],
        const SizedBox(height: 12),
        Expanded(
          child: ListView.separated(
            controller: useScrollController ? _episodesScrollCtrl : null,
            padding: EdgeInsets.zero,
            itemCount: _episodes.length,
            separatorBuilder: (_, _) => const SizedBox(height: 8),
            itemBuilder: (_, i) => _buildEpisodeTile(_episodes[i], i, disabled),
          ),
        ),
      ],
    );
  }

  Widget _buildApplyingBody() {
    final base = _activeMatch != null && _episodes.isNotEmpty
        ? _buildEpisodesBody(
            key: const ValueKey('applying-episodes'),
            disabled: true,
            useScrollController: false,
          )
        : _buildResultsBody(
            key: const ValueKey('applying-results'),
            disabled: true,
          );

    return Stack(
      key: const ValueKey('applying'),
      fit: StackFit.expand,
      children: [
        base,
        Positioned.fill(
          child: ColoredBox(color: Colors.black.withValues(alpha: 0.18)),
        ),
        const Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              AppLoadingRing(size: 22, color: Colors.white),
              SizedBox(height: 12),
              Text(
                '正在加载弹幕…',
                style: TextStyle(color: Colors.white70, fontSize: 12),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildEpisodesHeader({required bool disabled}) {
    return Row(
      children: [
        IconButton(
          onPressed: disabled ? null : _backToResults,
          iconSize: 18,
          visualDensity: VisualDensity.compact,
          icon: const Icon(Icons.arrow_back, color: Colors.white70),
          tooltip: '返回',
        ),
        const SizedBox(width: 4),
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                _activeMatch?.animeTitle ?? '选择分集',
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
                style: const TextStyle(
                  color: Colors.white,
                  fontSize: 14,
                  fontWeight: FontWeight.w600,
                ),
              ),
              const SizedBox(height: 2),
              const Text(
                '选择要加载的集数',
                style: TextStyle(color: Colors.white54, fontSize: 12),
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildMessageBanner() {
    final color = _messageIsError ? Colors.redAccent : _kAccent;
    final icon = _messageIsError ? Icons.error_outline : Icons.info_outline;

    return Container(
      width: double.infinity,
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
      decoration: BoxDecoration(
        color: color.withValues(alpha: 0.12),
        borderRadius: BorderRadius.circular(10),
        border: Border.all(color: color.withValues(alpha: 0.35)),
      ),
      child: Row(
        children: [
          Icon(icon, size: 16, color: color),
          const SizedBox(width: 8),
          Expanded(
            child: Text(
              _messageText ?? '',
              style: const TextStyle(color: Colors.white70, fontSize: 12),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildResultTile(DanmakuMatchCandidate match, bool disabled) {
    final highlighted =
        _flashEpisodeId == match.episodeId &&
        _flashSource?.id == match.source.id;
    final canDrill = match.animeId > 0;
    final subtitle = match.episodeTitle.isNotEmpty
        ? match.episodeTitle
        : canDrill
        ? '进入分集列表后选择具体集数'
        : '直接加载当前搜索结果';
    final showTargetHint = widget.targetEpisode != null && canDrill;

    return InkWell(
      onTap: disabled
          ? null
          : () {
              if (canDrill) {
                _openAnime(match);
              } else {
                _applyDirect(match);
              }
            },
      borderRadius: BorderRadius.circular(10),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 100),
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
        decoration: BoxDecoration(
          color: highlighted
              ? Colors.white12
              : Colors.white.withValues(alpha: 0.04),
          borderRadius: BorderRadius.circular(10),
          border: Border.all(
            color: highlighted
                ? Colors.lightBlueAccent.withValues(alpha: 0.7)
                : Colors.white.withValues(alpha: 0.08),
          ),
        ),
        child: Row(
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    match.animeTitle,
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 13,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    subtitle,
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(
                      color: Colors.white54,
                      fontSize: 12,
                      height: 1.35,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    match.source.displayName,
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(color: Colors.white38, fontSize: 11),
                  ),
                  if (showTargetHint) ...[
                    const SizedBox(height: 4),
                    Row(
                      children: [
                        const Icon(
                          Icons.adjust,
                          size: 12,
                          color: Colors.white38,
                        ),
                        const SizedBox(width: 4),
                        Expanded(
                          child: Text(
                            '目标：${formatEpisodeNumber(widget.targetEpisode)}（点击选择）',
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style: const TextStyle(
                              color: Colors.white38,
                              fontSize: 11,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ],
                ],
              ),
            ),
            const SizedBox(width: 12),
            _buildResultAffordance(canDrill: canDrill),
          ],
        ),
      ),
    );
  }

  Widget _buildResultAffordance({required bool canDrill}) {
    if (canDrill) {
      return const Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text('选择集数', style: TextStyle(color: Colors.white54, fontSize: 11)),
          SizedBox(width: 2),
          Icon(Icons.chevron_right, size: 16, color: Colors.white54),
        ],
      );
    }

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      decoration: BoxDecoration(
        color: _kAccent.withValues(alpha: 0.16),
        borderRadius: BorderRadius.circular(999),
        border: Border.all(color: _kAccent.withValues(alpha: 0.4)),
      ),
      child: const Text(
        '直接加载',
        style: TextStyle(
          color: Colors.white,
          fontSize: 11,
          fontWeight: FontWeight.w600,
        ),
      ),
    );
  }

  Widget _buildEpisodeTile(
    DanmakuBangumiEpisode episode,
    int index,
    bool disabled,
  ) {
    final highlighted = _flashEpisodeId == episode.episodeId;
    final epNum = episode.episodeNumber.trim();
    final episodeLabel = epNum.isEmpty
        ? formatEpisodeNumber(index + 1)!
        : '第$epNum集';

    return InkWell(
      onTap: disabled || _activeMatch == null
          ? null
          : () => _applyEpisode(_activeMatch!, episode),
      borderRadius: BorderRadius.circular(10),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 100),
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
        decoration: BoxDecoration(
          color: highlighted
              ? Colors.white12
              : Colors.white.withValues(alpha: 0.04),
          borderRadius: BorderRadius.circular(10),
          border: Border.all(
            color: highlighted
                ? Colors.lightBlueAccent.withValues(alpha: 0.7)
                : Colors.white.withValues(alpha: 0.08),
          ),
        ),
        child: Row(
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    episodeLabel,
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 13,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                  if (episode.episodeTitle.isNotEmpty) ...[
                    const SizedBox(height: 4),
                    Text(
                      episode.episodeTitle,
                      maxLines: 2,
                      overflow: TextOverflow.ellipsis,
                      style: const TextStyle(
                        color: Colors.white54,
                        fontSize: 12,
                        height: 1.35,
                      ),
                    ),
                  ],
                ],
              ),
            ),
            const SizedBox(width: 12),
            const Text(
              '点击加载',
              style: TextStyle(color: Colors.white54, fontSize: 11),
            ),
          ],
        ),
      ),
    );
  }
}
