import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../core/chat/active_session_notifier.dart';
import '../../../core/chat/chat_notifier.dart';
import '../../../core/chat/session_closure_notifier.dart';
import '../../../core/constants.dart';
import '../widgets/pricing_bottom_sheet.dart';

// Chat theme colors
const _kUserBubbleColor = Color(0xFFD4929A);
const _kBgTint = Color(0xFFF5D0D6);
const _kBannerColor = Color(0xFFC4868F);
const _kAccentPink = Color(0xFFBE7C8A);
const _kEndedBannerColor = Color(0xFFFFE0B2); // soft amber for early-end notice
const _kEndedBannerText = Color(0xFF8B5A00);

class ChatScreen extends ConsumerStatefulWidget {
  final String sessionId;
  final String mitraName;

  const ChatScreen({super.key, required this.sessionId, required this.mitraName});

  @override
  ConsumerState<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends ConsumerState<ChatScreen> {
  final _messageController = TextEditingController();
  final _goodbyeController = TextEditingController();
  final _scrollController = ScrollController();
  Timer? _typingThrottle;
  bool _showBestieBanner = true;
  bool _showUserBanner = true;
  bool _expiredDialogShown = false;

  @override
  void initState() {
    super.initState();
    // The chat WebSocket is owned globally by `App` (see main.dart).
    // We just ask it to be on this session — no-op if it already is.
    Future.microtask(() {
      // Reset any closure state left over from a prior session view (the
      // closure notifier is keepAlive, so e.g. `ClosureCompleteData` from
      // the last goodbye submission would otherwise leak into this mount
      // and suppress the goodbye composer for a fresh `closing` session).
      ref.read(sessionClosureProvider.notifier).reset();
      ref.read(chatProvider.notifier).connectIfNotConnected(widget.sessionId);
    });
  }

  @override
  void dispose() {
    _messageController.dispose();
    _goodbyeController.dispose();
    _scrollController.dispose();
    _typingThrottle?.cancel();
    super.dispose();
    // Intentionally do NOT disconnect the WS here. The global lifecycle in
    // `App` decides when to disconnect (logout / no active session).
  }

  void _scrollToBottom() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_scrollController.hasClients) {
        _scrollController.animateTo(
          _scrollController.position.maxScrollExtent,
          duration: const Duration(milliseconds: 200),
          curve: Curves.easeOut,
        );
      }
    });
  }

  void _onTextChanged(String text) {
    if (_typingThrottle?.isActive ?? false) return;
    ref.read(chatProvider.notifier).sendTyping();
    _typingThrottle = Timer(const Duration(seconds: 2), () {});
  }

  void _sendMessage() {
    final text = _messageController.text.trim();
    if (text.isEmpty) return;
    ref.read(chatProvider.notifier).sendMessage(text);
    _messageController.clear();
    _scrollToBottom();
  }

  void _exitChat() {
    if (context.canPop()) {
      context.pop();
    } else {
      context.go('/home');
    }
  }

  Future<void> _showSessionExpiredDialog() async {
    if (_expiredDialogShown) return;
    _expiredDialogShown = true;
    if (!mounted) return;
    await showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (dialogContext) => AlertDialog(
        title: const Text('Waktu Curhat Berakhir'),
        content: const Text(
          'Sesi curhatmu sudah habis waktunya. Kamu bisa menutup obrolan atau memperpanjang waktu untuk lanjut bicara.',
        ),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.of(dialogContext).pop();
              _exitChat();
            },
            child: const Text('Tutup'),
          ),
          ElevatedButton(
            onPressed: () {
              Navigator.of(dialogContext).pop();
              PricingBottomSheet.showForExtension(context, sessionId: widget.sessionId);
            },
            child: const Text('Perpanjang'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final chatState = ref.watch(chatProvider);
    final closureState = ref.watch(sessionClosureProvider);

    // Listen for closure complete to navigate home
    ref.listen(sessionClosureProvider, (prev, next) {
      if (next is ClosureCompleteData) {
        // Make doubly sure home picks up the cleared session.
        ref.invalidate(activeSessionProvider);
        context.go('/home');
      }
    });

    // Listen for chat state changes to manage closure state and timer-expired modal
    ref.listen(chatProvider, (prev, next) {
      if (next is ChatConnectedData) {
        // Early-end (mitra/customer ended before timer): show goodbye composer.
        if (next.sessionClosing && !next.sessionExpired) {
          final closure = ref.read(sessionClosureProvider);
          if (closure is ClosureInitialData) {
            ref.read(sessionClosureProvider.notifier).declineExtension();
          }
        }
        // Timer-expired: show non-dismissible modal once on false→true flip.
        final wasExpired = prev is ChatConnectedData && prev.sessionExpired;
        if (next.sessionExpired && !wasExpired) {
          _showSessionExpiredDialog();
        }
        if (!next.sessionPaused && !next.sessionExpired && !next.sessionClosing) {
          final closure = ref.read(sessionClosureProvider);
          if (closure is! ClosureInitialData) {
            ref.read(sessionClosureProvider.notifier).reset();
          }
          // If we're back to a healthy active state, allow the modal to fire
          // again on a later expiry (e.g. after extension then re-expiry).
          _expiredDialogShown = false;
        }
        _scrollToBottom();
        final unread = next.messages
            .where((m) => m.senderType == UserType.mitra && m.status != MessageStatus.read)
            .map((m) => m.id)
            .toList();
        if (unread.isNotEmpty) {
          ref.read(chatProvider.notifier).markRead(unread);
          // Optimistically clear the home badge.
          ref.read(activeSessionProvider.notifier).markRead();
        }
      }
    });

    return PopScope(
      canPop: false,
      onPopInvokedWithResult: (didPop, _) {
        if (!didPop) _exitChat();
      },
      child: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.white,
          foregroundColor: Colors.black,
          elevation: 0.5,
          centerTitle: true,
          leading: IconButton(
            icon: const Icon(Icons.chevron_left, size: 28),
            onPressed: _exitChat,
          ),
          title: Text(widget.mitraName),
          actions: [
            if (chatState is ChatConnectedData && chatState.remainingSeconds != null)
              Padding(
                padding: const EdgeInsets.only(right: 16),
                child: Center(
                  child: Text(
                    '${chatState.remainingSeconds}s',
                    style: TextStyle(
                      color: chatState.remainingSeconds! < 30 ? Colors.red : Colors.black,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              ),
          ],
        ),
        body: _buildBody(chatState, closureState),
      ),
    );
  }

  Widget _buildBody(ChatData chatState, SessionClosureData closureState) {
    if (chatState is ChatConnectingData) {
      return const Center(child: CircularProgressIndicator());
    }
    if (chatState is ChatErrorData) {
      return Center(child: Text(chatState.message));
    }
    if (chatState is ChatConnectedData) {
      return _buildChatBody(chatState, closureState);
    }
    return const SizedBox.shrink();
  }

  Widget _buildChatBody(ChatConnectedData state, SessionClosureData closureState) {
    // Show goodbye composer when closure flow is in goodbye/submitting OR when
    // we mounted directly into a `closing` session (e.g. opened from history).
    // The chatProvider listener can't catch this case because it only fires on
    // transitions, not the current state at mount time.
    // Suppress when the customer has already submitted their goodbye — the
    // session can stay in `closing` while waiting for the mitra to submit
    // their own message or for the 5-min grace timer to auto-complete.
    final shouldShowGoodbye = !state.goodbyeSubmitted &&
        (closureState is ClosureShowGoodbyeData ||
            closureState is ClosureSubmittingData ||
            (state.sessionClosing &&
                !state.sessionExpired &&
                closureState is! ClosureCompleteData));
    if (shouldShowGoodbye) {
      return _buildGoodbyeView(closureState);
    }

    if (state.sessionClosing && state.goodbyeSubmitted) {
      return _buildAwaitingMitraGoodbyeView(state);
    }

    if (state.sessionPaused) {
      return _buildPausedView();
    }

    return Stack(
      children: [
        // Background pattern
        Positioned.fill(
          child: Container(
            color: _kBgTint,
            child: Image.asset(
              'assets/images/chat_pattern.png',
              repeat: ImageRepeat.repeat,
              fit: BoxFit.none,
            ),
          ),
        ),
        // Content
        Column(
          children: [
            // Entry banners
            if (_showBestieBanner)
              _buildEntryBanner(
                '[Bestie] Sudah Memasuki Ruangan',
                () => setState(() => _showBestieBanner = false),
              ),
            if (_showUserBanner)
              _buildEntryBanner(
                '[User] Sudah Memasuki Ruangan',
                () => setState(() => _showUserBanner = false),
              ),
            // Messages
            Expanded(
              child: ListView.builder(
                controller: _scrollController,
                padding: const EdgeInsets.all(16),
                itemCount: state.messages.length,
                itemBuilder: (context, index) {
                  final msg = state.messages[index];
                  final isMe = msg.senderType == UserType.customer;
                  return _buildMessageBubble(msg, isMe);
                },
              ),
            ),
            // Typing indicator
            if (state.isOtherTyping)
              const Padding(
                padding: EdgeInsets.symmetric(horizontal: 16, vertical: 4),
                child: Align(
                  alignment: Alignment.centerLeft,
                  child: Text('Bestie sedang mengetik...', style: TextStyle(color: Colors.grey, fontSize: 12)),
                ),
              ),
            // Input bar — disabled when timer expired (modal handles next step)
            if (!state.sessionExpired) _buildInputBar(),
          ],
        ),
      ],
    );
  }

  Widget _buildEntryBanner(String text, VoidCallback onDismiss) {
    return Container(
      color: _kBannerColor,
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
      child: Row(
        children: [
          const Icon(Icons.volume_up, color: Colors.white, size: 18),
          const SizedBox(width: 8),
          Expanded(
            child: Text(text, style: const TextStyle(color: Colors.white, fontSize: 13)),
          ),
          GestureDetector(
            onTap: onDismiss,
            child: const Icon(Icons.close, color: Colors.white, size: 18),
          ),
        ],
      ),
    );
  }

  Widget _buildMessageBubble(ChatMessage msg, bool isMe) {
    return Align(
      alignment: isMe ? Alignment.centerRight : Alignment.centerLeft,
      child: Container(
        margin: const EdgeInsets.symmetric(vertical: 4),
        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
        constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.75),
        decoration: BoxDecoration(
          color: isMe ? _kUserBubbleColor : Colors.white,
          borderRadius: BorderRadius.circular(16),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Text(msg.content, style: const TextStyle(fontSize: 15)),
            const SizedBox(height: 4),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  '${msg.createdAt.hour.toString().padLeft(2, '0')}:${msg.createdAt.minute.toString().padLeft(2, '0')}',
                  style: TextStyle(fontSize: 10, color: isMe ? Colors.white70 : Colors.grey),
                ),
                if (isMe) ...[
                  const SizedBox(width: 4),
                  _buildStatusIcon(msg.status),
                ],
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildStatusIcon(String status) {
    switch (status) {
      case 'sending':
        return const Icon(Icons.access_time, size: 14, color: Colors.white70);
      case MessageStatus.sent:
        return const Icon(Icons.check, size: 14, color: Colors.white70);
      case MessageStatus.delivered:
        return const Icon(Icons.done_all, size: 14, color: Colors.white70);
      case MessageStatus.read:
        return const Icon(Icons.done_all, size: 14, color: Colors.white);
      default:
        return const SizedBox.shrink();
    }
  }

  Widget _buildInputBar() {
    return SafeArea(
      child: Container(
        padding: const EdgeInsets.all(8),
        color: Colors.white,
        child: Row(
          children: [
            Expanded(
              child: TextField(
                controller: _messageController,
                onChanged: _onTextChanged,
                textInputAction: TextInputAction.send,
                onSubmitted: (_) => _sendMessage(),
                decoration: InputDecoration(
                  hintText: 'Ketik Pesan',
                  hintStyle: TextStyle(color: Colors.grey.shade400),
                  filled: true,
                  fillColor: Colors.grey.shade100,
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(24),
                    borderSide: BorderSide.none,
                  ),
                  contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                ),
              ),
            ),
            const SizedBox(width: 8),
            Container(
              decoration: const BoxDecoration(
                color: _kAccentPink,
                shape: BoxShape.circle,
              ),
              child: IconButton(
                icon: const Icon(Icons.send, color: Colors.white, size: 20),
                onPressed: _sendMessage,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildGoodbyeView(SessionClosureData closureState) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(32),
      child: Column(
        children: [
          // Early-end banner — visually distinct, separate from the closing
          // composer below. We don't surface "Perpanjang" in this flow.
          Container(
            width: double.infinity,
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            decoration: BoxDecoration(
              color: _kEndedBannerColor,
              borderRadius: BorderRadius.circular(8),
            ),
            child: const Row(
              children: [
                Icon(Icons.info_outline, color: _kEndedBannerText, size: 20),
                SizedBox(width: 8),
                Expanded(
                  child: Text(
                    'Sesi telah ditutup oleh Bestie',
                    style: TextStyle(color: _kEndedBannerText, fontWeight: FontWeight.w600),
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 32),
          const Icon(Icons.waving_hand, size: 64, color: Colors.amber),
          const SizedBox(height: 16),
          const Text('Pesan Penutup', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
          const SizedBox(height: 8),
          const Text('Tuliskan pesan terakhirmu untuk Bestie', textAlign: TextAlign.center),
          const SizedBox(height: 24),
          TextField(
            controller: _goodbyeController,
            maxLines: 3,
            decoration: InputDecoration(
              hintText: 'Terima kasih, Bestie...',
              border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
            ),
          ),
          const SizedBox(height: 16),
          ElevatedButton(
            onPressed: closureState is ClosureSubmittingData
                ? null
                : () {
                    final text = _goodbyeController.text.trim();
                    if (text.isNotEmpty) {
                      ref.read(sessionClosureProvider.notifier).submitGoodbye(
                        widget.sessionId, text,
                      );
                    }
                  },
            child: closureState is ClosureSubmittingData
                ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
                : const Text('Kirim & Selesai'),
          ),
        ],
      ),
    );
  }

  Widget _buildPausedView() {
    return const Center(
      child: Padding(
        padding: EdgeInsets.all(32),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(),
            SizedBox(height: 24),
            Text('Menunggu konfirmasi Bestie...', style: TextStyle(fontSize: 18)),
            SizedBox(height: 8),
            Text('Chat dijeda sementara', style: TextStyle(color: Colors.grey)),
          ],
        ),
      ),
    );
  }

  Widget _buildAwaitingMitraGoodbyeView(ChatConnectedData state) {
    return Stack(
      children: [
        Positioned.fill(
          child: Container(
            color: _kBgTint,
            child: Image.asset(
              'assets/images/chat_pattern.png',
              repeat: ImageRepeat.repeat,
              fit: BoxFit.none,
            ),
          ),
        ),
        Column(
          children: [
            Container(
              width: double.infinity,
              color: _kEndedBannerColor,
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
              child: const Row(
                children: [
                  Icon(Icons.hourglass_top, color: _kEndedBannerText, size: 20),
                  SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      'Pesan penutupmu sudah terkirim. Menunggu Bestie...',
                      style: TextStyle(color: _kEndedBannerText, fontWeight: FontWeight.w600),
                    ),
                  ),
                ],
              ),
            ),
            Expanded(
              child: ListView.builder(
                controller: _scrollController,
                padding: const EdgeInsets.all(16),
                itemCount: state.messages.length,
                itemBuilder: (context, index) {
                  final msg = state.messages[index];
                  final isMe = msg.senderType == UserType.customer;
                  return _buildMessageBubble(msg, isMe);
                },
              ),
            ),
          ],
        ),
      ],
    );
  }
}
