// nodes_page.dart — 节点页(置顶智能选择推荐卡 + 搜索 + 列表/双列网格)
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../l10n/app_text.dart';
import '../models/node.dart';
import '../pangolin_theme.dart';
import '../state/app_providers.dart';
import '../state/connection_provider.dart';
import '../state/nodes_provider.dart';
import '../widgets/app_top_bar.dart';
import '../widgets/country_code.dart';
import '../widgets/pangolin_icons.dart';
import '../widgets/server_tile.dart';
import '../widgets/smart_select_card.dart';

class NodesPage extends ConsumerStatefulWidget {
  const NodesPage({super.key, required this.isWide, required this.onPicked});
  final bool isWide;
  final VoidCallback onPicked;

  @override
  ConsumerState<NodesPage> createState() => _NodesPageState();
}

class _NodesPageState extends ConsumerState<NodesPage> {
  String _q = '';

  void _pick(String code) {
    ref.read(selectedNodeCodeProvider.notifier).state = code;
    ref.read(connectionProvider.notifier).onNodeChanged();
    widget.onPicked();
  }

  List<Node> _filtered(List<Node> nodes) {
    if (_q.trim().isEmpty) return nodes;
    final q = _q.toLowerCase();
    return nodes
        .where((n) => (n.nameZh + n.nameEn + n.code).toLowerCase().contains(q))
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    final c = context.pangolin;
    final t = ref.watch(appTextProvider);
    final selected = ref.watch(selectedNodeCodeProvider);
    final nodes = _filtered(ref.watch(nodesProvider).valueOrNull ?? const <Node>[]);
    final smart = selected == kSmartNodeCode;

    final smartCard = SmartSelectCard(t: t, selected: smart, onTap: () => _pick(kSmartNodeCode));
    final search = _SearchBox(hint: t.searchPh, onChanged: (v) => setState(() => _q = v));

    if (widget.isWide) {
      // 对照 dapp.jsx DServers：padding 4/28、网格 gap 10。智能卡置顶（CLAUDE.md §5 规范，三端一致）。
      return ListView(
        padding: const EdgeInsets.fromLTRB(28, 4, 28, 24),
        children: [
          smartCard,
          const SizedBox(height: 14),
          ConstrainedBox(constraints: const BoxConstraints(maxWidth: 380), child: search),
          const SizedBox(height: 14),
          GridView.count(
            crossAxisCount: 2,
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            mainAxisSpacing: 10,
            crossAxisSpacing: 10,
            childAspectRatio: 4.4,
            children: [
              for (final n in nodes)
                _NodeGridTile(node: n, lang: t.lang, active: !smart && n.code == selected, onTap: () => _pick(n.code)),
            ],
          ),
        ],
      );
    }

    // 窄屏:顶栏 + 标题 + 推荐卡 + 搜索 + 分组列表
    return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
      AppTopBar(brand: t.brand),
      PageTitle(title: t.chooseNode),
      Expanded(
        child: ListView(
          padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
          children: [
            smartCard,
            const SizedBox(height: 12),
            search,
            const SizedBox(height: 12),
            Container(
              decoration: BoxDecoration(
                color: c.surface,
                borderRadius: BorderRadius.circular(PangolinRadius.lg),
                border: Border.all(color: c.border),
                boxShadow: PangolinShadow.sm,
              ),
              clipBehavior: Clip.antiAlias,
              child: Column(children: [
                for (var i = 0; i < nodes.length; i++) ...[
                  ServerTile(
                    node: nodes[i],
                    lang: t.lang,
                    active: !smart && nodes[i].code == selected,
                    onTap: () => _pick(nodes[i].code),
                  ),
                  if (i < nodes.length - 1) Divider(height: 1, thickness: 1, color: c.border),
                ],
              ]),
            ),
          ],
        ),
      ),
    ]);
  }
}

class _SearchBox extends StatelessWidget {
  const _SearchBox({required this.hint, required this.onChanged});
  final String hint;
  final ValueChanged<String> onChanged;

  @override
  Widget build(BuildContext context) {
    final c = context.pangolin;
    return Container(
      decoration: BoxDecoration(color: c.bgSubtle, borderRadius: BorderRadius.circular(PangolinRadius.md)),
      padding: const EdgeInsets.symmetric(horizontal: 14),
      child: Row(children: [
        Icon(PangolinIcons.search, size: 18, color: c.fg3),
        const SizedBox(width: 10),
        Expanded(
          child: TextField(
            onChanged: onChanged,
            style: PangolinText.sm.copyWith(color: c.fg1, fontSize: 15),
            decoration: InputDecoration(
              isCollapsed: true,
              contentPadding: const EdgeInsets.symmetric(vertical: 12),
              border: InputBorder.none,
              hintText: hint,
              hintStyle: PangolinText.sm.copyWith(color: c.fg3, fontSize: 15),
            ),
          ),
        ),
      ]),
    );
  }
}

/// 宽屏双列网格中的节点块。
class _NodeGridTile extends StatelessWidget {
  const _NodeGridTile({required this.node, required this.lang, required this.active, required this.onTap});
  final Node node;
  final AppLang lang;
  final bool active;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    final c = context.pangolin;
    return Material(
      color: active ? c.accentSubtle : c.surface,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(PangolinRadius.lg),
        side: BorderSide(color: active ? c.accentBorder : c.border, width: 1.5),
      ),
      clipBehavior: Clip.antiAlias,
      child: InkWell(
        onTap: onTap,
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 11),
          child: Row(children: [
            CountryCode(code: node.code, active: active),
            const SizedBox(width: 12),
            Expanded(
              child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [
                Text(node.localizedName(lang),
                    overflow: TextOverflow.ellipsis,
                    style: PangolinText.sm.copyWith(color: c.fg1, fontWeight: FontWeight.w600, fontSize: 14.5)),
                Text(node.localizedSub(lang),
                    overflow: TextOverflow.ellipsis,
                    style: PangolinText.caption.copyWith(color: c.fg3, fontWeight: FontWeight.w400)),
              ]),
            ),
            const SizedBox(width: 8),
            Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.end, children: [
              Text(node.pingLabel, style: PangolinText.mono.copyWith(color: c.fg2, fontSize: 12)),
              const SizedBox(height: 5),
              SignalBars(ping: node.ping),
            ]),
            if (active) ...[const SizedBox(width: 8), Icon(PangolinIcons.check, size: 18, color: c.accent)],
          ]),
        ),
      ),
    );
  }
}
