import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../core/constants.dart';
import '../../../core/pairing/pairing_notifier.dart';
import '../../../core/theme/halo_tokens.dart';
import '../../../core/theme/widgets/widgets.dart';
import '../../payment/state/payment_draft_provider.dart';
import '../widgets/bestie_unavailable_dialog.dart';
import '../widgets/targeted_waiting_overlay.dart';

/// Searching screen — Phase 4 Stage 5 reskin of the SSearchPrompt soft-prompt
/// + searching panel. Renders three pairing-driven phases inline:
///
/// - `PairingSearchingData` → reflective-prompt cards + pulsing-dots panel.
/// - `PairingFailedData` (cause = noMitraAvailable / allMitrasRejected /
///   targetedMitraTimeout / targetedMitraRejected — i.e. the 5-minute blast
///   timeout) → moon panel + `coba cari lagi` / `kembali ke home` CTAs.
/// - `PairingTargetedWaitingData` → 20s targeted-wait overlay above the body.
///
/// Other transitions still route away as before:
///
/// - `PairingBestieFoundData` → `/chat/found` (S9 Match screen).
/// - `PairingActiveData` → `/chat/session/:id`.
/// - `PairingTargetedUnavailableData` → bestie-unavailable dialog overlay
///   (intermediate; payment stays confirmed; offers fallback-to-blast).
/// - `PairingCancelledData` → `/home`.
///
/// Per project memory ("Riverpod ref.listen in build is unsafe"), one-shot
/// transitions are wired through `ref.listenManual` in initState.
class SearchingScreen extends ConsumerStatefulWidget {
  const SearchingScreen({super.key});

  @override
  ConsumerState<SearchingScreen> createState() => _SearchingScreenState();
}

class _SearchingScreenState extends ConsumerState<SearchingScreen> {
  bool _unavailableDialogShown = false;

  @override
  void initState() {
    super.initState();
    ref.listenManual<PairingData>(pairingProvider, _onPairingState);
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!mounted) return;
      // Kick off the blast if pairing hasn't started yet — Phase 4's
      // multi-screen payment flow lands here without a startSearch call
      // (waiting → notif-gate → /chat/searching, no intermediate that
      // owned the call).
      final state = ref.read(pairingProvider);
      if (state is PairingInitialData) {
        final draft = ref.read(paymentDraftNotifierProvider);
        if (draft.paymentId != null) {
          // ignore: discarded_futures
          ref.read(pairingProvider.notifier).startSearch(
                paymentSessionId: draft.paymentId!,
                topicSensitivity: TopicSensitivity.regular,
              );
        }
      }
      _onPairingState(null, ref.read(pairingProvider));
    });
  }

  void _onPairingState(PairingData? prev, PairingData next) {
    if (!mounted) return;

    if (next is PairingBestieFoundData) {
      context.go('/chat/found', extra: {
        'sessionId': next.sessionId,
        'mitraName': next.mitraName,
      });
      return;
    }

    if (next is PairingActiveData) {
      context.go('/chat/session/${next.sessionId}', extra: next.mitraName);
      return;
    }

    if (next is PairingCancelledData) {
      context.go('/home');
      return;
    }

    if (next is PairingTargetedUnavailableData && !_unavailableDialogShown) {
      _unavailableDialogShown = true;
      // ignore: discarded_futures
      BestieOfflinePopup.show(
        context,
        variant: BestieOfflineVariant.returning,
        mitraName: next.mitraName,
        paymentSessionId: next.paymentSessionId,
        topicSensitivity: next.topicSensitivity,
      ).then((_) {
        if (mounted) _unavailableDialogShown = false;
      });
      return;
    }
  }

  @override
  Widget build(BuildContext context) {
    final pairingState = ref.watch(pairingProvider);

    return Scaffold(
      backgroundColor: HaloTokens.bg,
      body: SafeArea(
        child: Stack(
          children: [
            _SearchingBody(state: pairingState),
            if (pairingState is PairingTargetedWaitingData)
              TargetedWaitingOverlay(waiting: pairingState),
          ],
        ),
      ),
    );
  }
}

class _SearchingBody extends ConsumerWidget {
  final PairingData state;
  const _SearchingBody({required this.state});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isTimeout = state is PairingFailedData;
    final isTargetedWaiting = state is PairingTargetedWaitingData;
    final errorMessage =
        state is PairingErrorData ? (state as PairingErrorData).message : null;

    return Padding(
      padding: const EdgeInsets.fromLTRB(
        HaloSpacing.s24,
        HaloSpacing.s24,
        HaloSpacing.s24,
        HaloSpacing.s32,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          const Expanded(
            child: SingleChildScrollView(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Text(
                    'sambil nunggu, coba pikirin sebentar 🤍',
                    style: TextStyle(
                      fontFamily: HaloTokens.fontDisplay,
                      fontSize: 24,
                      height: 30 / 24,
                      fontWeight: FontWeight.w700,
                      color: HaloTokens.brandDark,
                      letterSpacing: -0.4,
                    ),
                  ),
                  SizedBox(height: HaloSpacing.s8),
                  Text(
                    'gausah dipikirin formatnya. ngalir aja gimana enaknya buat kamu.',
                    style: TextStyle(
                      fontFamily: HaloTokens.fontBody,
                      fontSize: 14,
                      height: 22 / 14,
                      color: HaloTokens.inkSoft,
                    ),
                  ),
                  SizedBox(height: HaloSpacing.s20),
                  _PromptCard('apa yang lagi paling kamu rasain hari ini?'),
                  SizedBox(height: HaloSpacing.s8),
                  _PromptCard('kapan terakhir kamu ngerasa lega?'),
                  SizedBox(height: HaloSpacing.s8),
                  _PromptCard('ada satu hal yang pengen banget kamu cerita...'),
                ],
              ),
            ),
          ),
          if (errorMessage != null) ...[
            const SizedBox(height: HaloSpacing.s16),
            _ErrorBanner(message: errorMessage),
          ],
          const SizedBox(height: HaloSpacing.s16),
          isTimeout
              ? const _TimeoutPanel()
              : _SearchingPanel(targetedWaiting: isTargetedWaiting),
          if (isTimeout) ...[
            const SizedBox(height: HaloSpacing.s12),
            HaloButton(
              label: 'coba cari lagi',
              fullWidth: true,
              size: HaloButtonSize.lg,
              onPressed: () {
                ref.read(pairingProvider.notifier).reset();
                context.go('/payment/entry');
              },
            ),
            const SizedBox(height: HaloSpacing.s8),
            HaloButton(
              label: 'kembali ke home',
              variant: HaloButtonVariant.ghost,
              fullWidth: true,
              onPressed: () {
                ref.read(pairingProvider.notifier).reset();
                context.go('/home');
              },
            ),
          ] else if (!isTargetedWaiting) ...[
            const SizedBox(height: HaloSpacing.s12),
            HaloButton(
              label: 'batalkan',
              variant: HaloButtonVariant.ghost,
              fullWidth: true,
              onPressed: () =>
                  ref.read(pairingProvider.notifier).cancelSearch(),
            ),
          ],
        ],
      ),
    );
  }
}

class _PromptCard extends StatelessWidget {
  final String text;
  const _PromptCard(this.text);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(HaloSpacing.s16),
      decoration: BoxDecoration(
        color: HaloTokens.surface,
        borderRadius: BorderRadius.circular(14),
        border: Border.all(color: HaloTokens.border),
      ),
      child: Text(
        text,
        style: const TextStyle(
          fontFamily: HaloTokens.fontBody,
          fontSize: 13,
          height: 20 / 13,
          color: HaloTokens.ink,
        ),
      ),
    );
  }
}

class _SearchingPanel extends StatelessWidget {
  final bool targetedWaiting;
  const _SearchingPanel({required this.targetedWaiting});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(HaloSpacing.s20),
      decoration: BoxDecoration(
        color: HaloTokens.brandSofter,
        borderRadius: BorderRadius.circular(18),
        border: Border.all(color: HaloTokens.brandSoft),
      ),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          const _PulsingDots(),
          const SizedBox(width: HaloSpacing.s16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  targetedWaiting ? 'menghubungi bestie...' : 'lagi nyari bestie...',
                  style: const TextStyle(
                    fontFamily: HaloTokens.fontBody,
                    fontSize: 13,
                    fontWeight: FontWeight.w600,
                    color: HaloTokens.brandDark,
                  ),
                ),
                const SizedBox(height: 2),
                const Text(
                  'biasanya 30 detik · sambil baca prompt aja',
                  style: TextStyle(
                    fontFamily: HaloTokens.fontBody,
                    fontSize: 11.5,
                    color: HaloTokens.inkSoft,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _TimeoutPanel extends StatelessWidget {
  const _TimeoutPanel();

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(HaloSpacing.s20),
      decoration: BoxDecoration(
        color: HaloTokens.brandSofter,
        borderRadius: BorderRadius.circular(18),
        border: Border.all(color: HaloTokens.brandSoft),
      ),
      child: const Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text('🌙', style: TextStyle(fontSize: 26)),
          SizedBox(width: HaloSpacing.s16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'masih nyari nih...',
                  style: TextStyle(
                    fontFamily: HaloTokens.fontBody,
                    fontSize: 13,
                    fontWeight: FontWeight.w600,
                    color: HaloTokens.brandDark,
                  ),
                ),
                SizedBox(height: 2),
                Text(
                  'bestie lagi rame. coba cari lagi atau kembali nanti',
                  style: TextStyle(
                    fontFamily: HaloTokens.fontBody,
                    fontSize: 11.5,
                    height: 16 / 11.5,
                    color: HaloTokens.inkSoft,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _PulsingDots extends StatefulWidget {
  const _PulsingDots();

  @override
  State<_PulsingDots> createState() => _PulsingDotsState();
}

class _PulsingDotsState extends State<_PulsingDots>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1400),
    )..repeat();
  }

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

  double _scaleAt(double t, double phase) {
    // Mirrors the keyframe in v3.jsx: (0,80,100) → 0.6 ; 40 → 1.
    final shifted = (t - phase) % 1.0;
    final eased = shifted < 0 ? shifted + 1.0 : shifted;
    if (eased < 0.4) {
      return 0.6 + (1.0 - 0.6) * (eased / 0.4);
    } else if (eased < 0.8) {
      return 1.0 - (1.0 - 0.6) * ((eased - 0.4) / 0.4);
    }
    return 0.6;
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, _) {
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: List.generate(3, (i) {
            final scale = _scaleAt(_controller.value, i * 0.16);
            return Padding(
              padding: EdgeInsets.only(right: i == 2 ? 0 : 4),
              child: Transform.scale(
                scale: scale,
                child: Container(
                  width: 8,
                  height: 8,
                  decoration: const BoxDecoration(
                    color: HaloTokens.brand,
                    shape: BoxShape.circle,
                  ),
                ),
              ),
            );
          }),
        );
      },
    );
  }
}

class _ErrorBanner extends StatelessWidget {
  final String message;
  const _ErrorBanner({required this.message});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(HaloSpacing.s12),
      decoration: BoxDecoration(
        color: const Color(0x14D86B6B),
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: HaloTokens.danger.withValues(alpha: 0.4)),
      ),
      child: Text(
        message,
        textAlign: TextAlign.center,
        style: const TextStyle(
          fontFamily: HaloTokens.fontBody,
          fontSize: 13,
          color: HaloTokens.danger,
        ),
      ),
    );
  }
}
