// connect_button.dart — 核心连接键(严格三态:off / connecting / on)
//
// 纯展示组件:状态由外部状态机(connection_provider)注入,点击只回调
// onTap(派发事件),绝不在组件内本地翻转状态——禁止乐观显示。
//
// 三态(design/CLAUDE.md §5):
//   off        暖灰底 sand-100 + clay power 图标 + 虚线轨道环 + 「点击连接」
//   connecting clay 实底 + 旋转进度弧 + 旋转 loader
//   on         success 实底 + 白盾勾 + 满白环 + 圆内计时 + 「已加密」+ 绿光晕
// 背景在纯色间切换仅过渡 box-shadow / background-color,不用 transition: all。
import 'package:flutter/material.dart';

import '../pangolin_theme.dart';
import '../state/connection_provider.dart';
import 'pangolin_icons.dart';

class ConnectButton extends StatefulWidget {
  const ConnectButton({
    super.key,
    required this.phase,
    required this.onTap,
    required this.offLabel,
    required this.secureLabel,
    this.elapsed = Duration.zero,
    this.size = 208,
  });

  final VpnPhase phase;
  final VoidCallback onTap;

  /// off 态圆内文字(如「点击连接」/「CONNECT」)。
  final String offLabel;

  /// on 态圆内计时下方文字(如「已加密」/「SECURE」)。
  final String secureLabel;
  final Duration elapsed;
  final double size;

  @override
  State<ConnectButton> createState() => _ConnectButtonState();
}

class _ConnectButtonState extends State<ConnectButton> with SingleTickerProviderStateMixin {
  late final AnimationController _spin =
      AnimationController(vsync: this, duration: const Duration(milliseconds: 1400))..repeat();

  @override
  void dispose() {
    _spin.dispose();
    super.dispose();
  }

  String _fmt(Duration d) {
    String two(int n) => n.toString().padLeft(2, '0');
    return '${two(d.inHours)}:${two(d.inMinutes % 60)}:${two(d.inSeconds % 60)}';
  }

  @override
  Widget build(BuildContext context) {
    final c = context.pangolin;
    final s = widget.phase;

    final Color fill = switch (s) {
      VpnPhase.off => c.bgSubtle,
      VpnPhase.connecting => c.accent,
      VpnPhase.on => c.success,
    };
    final Color fg = s == VpnPhase.off ? c.accent : PangolinColors.white;
    final IconData icon = switch (s) {
      VpnPhase.off => PangolinIcons.power,
      VpnPhase.connecting => PangolinIcons.loader,
      VpnPhase.on => PangolinIcons.shieldCheck,
    };

    // off 用柔和阴影;connecting/on 增加同色光晕环(box-shadow,不动背景计算)。
    final List<BoxShadow> glow = s == VpnPhase.off
        ? PangolinShadow.md
        : [
            BoxShadow(
              color: (s == VpnPhase.on ? c.success : c.accent).withValues(alpha: 0.18),
              blurRadius: 0,
              spreadRadius: 9,
            ),
            ...PangolinShadow.lg,
          ];

    return Semantics(
      button: true,
      label: widget.offLabel,
      child: GestureDetector(
        onTap: widget.onTap,
        child: AnimatedContainer(
          duration: PangolinMotion.slow,
          curve: PangolinMotion.easeOut,
          width: widget.size,
          height: widget.size,
          decoration: BoxDecoration(color: fill, shape: BoxShape.circle, boxShadow: glow),
          child: Stack(
            alignment: Alignment.center,
            children: [
              Positioned.fill(
                child: AnimatedBuilder(
                  animation: _spin,
                  builder: (_, __) => CustomPaint(
                    painter: _RingPainter(
                      phase: s,
                      track: PangolinColors.sand200,
                      progress: PangolinColors.white,
                      turns: s == VpnPhase.connecting ? _spin.value : 0,
                    ),
                  ),
                ),
              ),
              // connecting 时图标也旋转(对齐 React loader spin)
              if (s == VpnPhase.connecting)
                RotationTransition(
                  turns: _spin,
                  child: Icon(icon, size: 50, color: fg),
                )
              else
                Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Icon(icon, size: 50, color: fg),
                    const SizedBox(height: 6),
                    if (s == VpnPhase.on) ...[
                      Text(_fmt(widget.elapsed),
                          style: PangolinText.mono
                              .copyWith(color: fg, fontSize: 18, fontWeight: FontWeight.w600)),
                      Text(widget.secureLabel,
                          style: PangolinText.caption.copyWith(
                              color: fg.withValues(alpha: 0.9),
                              fontSize: 10,
                              fontWeight: FontWeight.w700,
                              letterSpacing: 1.0)),
                    ] else
                      Text(widget.offLabel,
                          style: PangolinText.caption.copyWith(
                              color: fg, fontSize: 13, fontWeight: FontWeight.w700, letterSpacing: 0.5)),
                  ],
                ),
            ],
          ),
        ),
      ),
    );
  }
}

class _RingPainter extends CustomPainter {
  _RingPainter({required this.phase, required this.track, required this.progress, required this.turns});
  final VpnPhase phase;
  final Color track;
  final Color progress;
  final double turns;

  @override
  void paint(Canvas canvas, Size size) {
    final center = size.center(Offset.zero);
    final radius = size.width / 2 - 8;
    final rect = Rect.fromCircle(center: center, radius: radius);

    switch (phase) {
      case VpnPhase.off:
        final p = Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 3
          ..strokeCap = StrokeCap.round
          ..color = track;
        const dash = 0.045, gap = 0.11;
        for (double a = 0; a < 6.283; a += dash + gap) {
          canvas.drawArc(rect, a, dash, false, p);
        }
      case VpnPhase.connecting:
        final base = Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 4
          ..color = progress.withValues(alpha: 0.3);
        canvas.drawArc(rect, 0, 6.283, false, base);
        final arc = Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 4
          ..strokeCap = StrokeCap.round
          ..color = progress;
        canvas.drawArc(rect, turns * 6.283, 1.6, false, arc);
      case VpnPhase.on:
        final p = Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 4
          ..strokeCap = StrokeCap.round
          ..color = progress.withValues(alpha: 0.85);
        canvas.drawArc(rect, 0, 6.283, false, p);
    }
  }

  @override
  bool shouldRepaint(_RingPainter old) => old.turns != turns || old.phase != phase;
}
