import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:get/get.dart';
import 'package:audioplayers/audioplayers.dart';
import '../models/message_model.dart';
import '../theme/app_theme.dart';
import '../services/whatsapp_service.dart';

// ─── Full-Screen Image Viewer ─────────────────────────────────────────────
class FullScreenImageViewer extends StatelessWidget {
  final Uint8List bytes;
  final String heroTag;

  const FullScreenImageViewer({
    super.key,
    required this.bytes,
    required this.heroTag,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        backgroundColor: Colors.black,
        iconTheme: const IconThemeData(color: Colors.white),
        elevation: 0,
      ),
      body: Center(
        child: Hero(
          tag: heroTag,
          child: InteractiveViewer(
            minScale: 0.5,
            maxScale: 5.0,
            child: Image.memory(bytes, fit: BoxFit.contain),
          ),
        ),
      ),
    );
  }
}

// ─── Message Bubble ───────────────────────────────────────────────────────
class MessageBubble extends StatelessWidget {
  final MessageModel message;

  const MessageBubble({super.key, required this.message});

  @override
  Widget build(BuildContext context) {
    final isMe  = message.fromMe;
    final isDark = AppTheme.isDark(context);

    final bg = isMe
        ? AppTheme.outgoingMsg(context)
        : AppTheme.incomingMsg(context);

    final radius = isMe
        ? const BorderRadius.only(
            topLeft:     Radius.circular(12),
            topRight:    Radius.circular(4),
            bottomLeft:  Radius.circular(12),
            bottomRight: Radius.circular(12),
          )
        : const BorderRadius.only(
            topLeft:     Radius.circular(4),
            topRight:    Radius.circular(12),
            bottomLeft:  Radius.circular(12),
            bottomRight: Radius.circular(12),
          );

    // Incoming message shadow/border in light mode
    final BoxDecoration decoration = BoxDecoration(
      color: bg,
      borderRadius: radius,
      boxShadow: [
        BoxShadow(
          color: Colors.black.withOpacity(isDark ? 0.2 : 0.08),
          blurRadius: 2,
          offset: const Offset(0, 1),
        ),
      ],
    );

    return Container(
      margin: EdgeInsets.only(
        top: 2,
        bottom: 2,
        left: isMe ? 60 : 8,
        right: isMe ? 8 : 60,
      ),
      child: Column(
        crossAxisAlignment:
            isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
        children: [
          // Tail + bubble
          Stack(
            children: [
              // Message bubble
              Container(
                constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width * 0.78,
                ),
                padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
                decoration: decoration,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    // Sender name in group chats (incoming only)
                    if (!isMe && message.author != null) ...[
                      Text(
                        message.author!,
                        style: const TextStyle(
                          color: AppTheme.primaryDark,
                          fontSize: 12.5,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      const SizedBox(height: 2),
                    ],

                    // Media
                    if (message.hasMedia) ...[
                      InteractiveMediaWidget(message: message),
                      const SizedBox(height: 4),
                    ],

                    // Text + time + ACK row
                    _buildTextTimeRow(context, isMe),
                  ],
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildTextTimeRow(BuildContext context, bool isMe) {
    // If body is empty (media-only message), just show time+ack
    final hasBody = message.body.trim().isNotEmpty;

    if (!hasBody && message.hasMedia) {
      // Show only time+ack at bottom right of media
      return Align(
        alignment: Alignment.bottomRight,
        child: _timeAckRow(context, isMe),
      );
    }

    return Wrap(
      alignment: WrapAlignment.end,
      crossAxisAlignment: WrapCrossAlignment.end,
      children: [
        if (hasBody)
          Text(
            message.body,
            style: TextStyle(
              color: AppTheme.textPrimary(context),
              fontSize: 15,
            ),
          ),
        const SizedBox(width: 4),
        _timeAckRow(context, isMe),
      ],
    );
  }

  Widget _timeAckRow(BuildContext context, bool isMe) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(
          _formatTime(message.timestamp),
          style: TextStyle(
            color: AppTheme.textSecondary(context),
            fontSize: 11,
          ),
        ),
        if (isMe) ...[
          const SizedBox(width: 3),
          _buildAckIcon(context, message.ack),
        ],
      ],
    );
  }

  // ── ACK icon ──────────────────────────────────────────────────────────────
  // Real WhatsApp ACK values from whatsapp-web.js:
  //  -1 = error
  //   0 = pending (clock icon)
  //   1 = sent (single grey tick ✓)
  //   2 = delivered/received (double grey tick ✓✓)
  //   3 = read/played (double BLUE tick ✓✓)
  Widget _buildAckIcon(BuildContext context, int ack) {
    switch (ack) {
      case -1:
      case 0:
        // Pending — clock
        return Icon(Icons.access_time_rounded,
            size: 14, color: AppTheme.textSecondary(context));
      case 1:
        // Sent — single grey tick
        return Icon(Icons.check_rounded,
            size: 16, color: AppTheme.textSecondary(context));
      case 2:
        // Delivered — double grey tick
        return Icon(Icons.done_all_rounded,
            size: 16, color: AppTheme.textSecondary(context));
      case 3:
        // Read — double blue tick
        return const Icon(Icons.done_all_rounded,
            size: 16, color: AppTheme.blueTick);
      default:
        return const SizedBox.shrink();
    }
  }

  String _formatTime(int timestamp) {
    if (timestamp == 0) return '';
    final dt = DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
    return DateFormat('h:mm a').format(dt);
  }
}

// ─── Interactive Media Widget ─────────────────────────────────────────────
class InteractiveMediaWidget extends StatefulWidget {
  final MessageModel message;

  const InteractiveMediaWidget({super.key, required this.message});

  @override
  State<InteractiveMediaWidget> createState() => _InteractiveMediaWidgetState();
}

class _InteractiveMediaWidgetState extends State<InteractiveMediaWidget> {
  final WhatsAppService _svc = Get.find<WhatsAppService>();
  bool _isLoading = false;

  // Audio player state
  final AudioPlayer _player = AudioPlayer();
  StreamSubscription? _posSub;
  StreamSubscription? _durSub;
  StreamSubscription? _stateSub;

  bool _isPlaying = false;
  double _audioProgress = 0.0;
  int _audioDurationSeconds = 1;
  int _audioCurrentSeconds = 0;

  @override
  void initState() {
    super.initState();
    _posSub = _player.onPositionChanged.listen((p) {
      if (mounted) {
        setState(() {
          _audioCurrentSeconds = p.inSeconds;
          if (_audioDurationSeconds > 0) {
            _audioProgress = p.inMilliseconds / (_audioDurationSeconds * 1000);
            if (_audioProgress > 1.0) _audioProgress = 1.0;
          }
        });
      }
    });

    _durSub = _player.onDurationChanged.listen((d) {
      if (mounted) {
        setState(() {
          _audioDurationSeconds = d.inSeconds > 0 ? d.inSeconds : 1;
        });
      }
    });

    _stateSub = _player.onPlayerStateChanged.listen((s) {
      if (mounted) {
        setState(() {
          _isPlaying = s == PlayerState.playing;
          if (s == PlayerState.completed) {
            _audioProgress = 0.0;
            _audioCurrentSeconds = 0;
            _isPlaying = false;
          }
        });
      }
    });
  }

  @override
  void dispose() {
    _posSub?.cancel();
    _durSub?.cancel();
    _stateSub?.cancel();
    _player.dispose();
    super.dispose();
  }

  void _toggleAudioPlayback(String base64Data) async {
    try {
      if (_isPlaying) {
        await _player.pause();
      } else {
        final bytes = base64Decode(base64Data);
        final safeId =
            widget.message.id.replaceAll(RegExp(r'[^a-zA-Z0-9]'), '');
        final tempDir = Directory.systemTemp;
        final tempFile = File('${tempDir.path}/voice_$safeId.mp3');

        if (!await tempFile.exists()) {
          await tempFile.writeAsBytes(bytes);
        }

        await _player.play(DeviceFileSource(tempFile.path));
      }
    } catch (e) {
      print('[AUDIO PLAYBACK ERROR] $e');
      Get.snackbar(
        'Playback Error',
        'Could not play audio message: $e',
        snackPosition: SnackPosition.BOTTOM,
        backgroundColor: Colors.redAccent.withOpacity(0.8),
        colorText: Colors.white,
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Obx(() {
      final cachedMedia = _svc.mediaCache[widget.message.id];

      if (cachedMedia != null) {
        return _buildDownloadedMedia(context, cachedMedia);
      }

      if (_isLoading) {
        return Container(
          padding: const EdgeInsets.all(16),
          width: 140,
          alignment: Alignment.center,
          decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.12),
            borderRadius: BorderRadius.circular(8),
          ),
          child: const SizedBox(
            width: 24,
            height: 24,
            child: CircularProgressIndicator(
                strokeWidth: 2, color: AppTheme.primary),
          ),
        );
      }

      // Tap to download placeholder
      return GestureDetector(
        onTap: _downloadMedia,
        child: Container(
          padding: const EdgeInsets.all(10),
          decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.10),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                width: 40,
                height: 40,
                decoration: BoxDecoration(
                  color: AppTheme.primary.withOpacity(0.15),
                  shape: BoxShape.circle,
                ),
                child: Icon(_getIcon(),
                    color: AppTheme.primary, size: 22),
              ),
              const SizedBox(width: 10),
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    _getLabel(),
                    style: TextStyle(
                        color: AppTheme.textPrimary(context),
                        fontWeight: FontWeight.w500,
                        fontSize: 13),
                  ),
                  const SizedBox(height: 2),
                  Row(
                    children: [
                      Icon(Icons.download_rounded,
                          size: 12,
                          color: AppTheme.textSecondary(context)),
                      const SizedBox(width: 3),
                      Text(
                        'Tap to download',
                        style: TextStyle(
                            color: AppTheme.textSecondary(context),
                            fontSize: 11),
                      ),
                    ],
                  ),
                ],
              ),
            ],
          ),
        ),
      );
    });
  }

  Future<void> _downloadMedia() async {
    setState(() => _isLoading = true);
    await _svc.downloadAndCacheMedia(widget.message.id);
    if (mounted) {
      setState(() => _isLoading = false);
    }
  }

  Widget _buildDownloadedMedia(BuildContext context, String base64Data) {
    final bytes = base64Decode(base64Data);

    // ── Image / Sticker ────────────────────────────────────────────────────
    if (widget.message.type == "image" || widget.message.type == "sticker") {
      final heroTag = 'img_${widget.message.id}';
      return GestureDetector(
        onTap: () {
          Navigator.of(context).push(
            PageRouteBuilder(
              opaque: false,
              barrierColor: Colors.black,
              pageBuilder: (_, __, ___) => FullScreenImageViewer(
                bytes: bytes,
                heroTag: heroTag,
              ),
              transitionsBuilder: (_, anim, __, child) =>
                  FadeTransition(opacity: anim, child: child),
            ),
          );
        },
        child: Hero(
          tag: heroTag,
          child: ClipRRect(
            borderRadius: BorderRadius.circular(8),
            child: ConstrainedBox(
              constraints: const BoxConstraints(maxHeight: 260),
              child: Image.memory(
                bytes,
                fit: BoxFit.cover,
                width: double.infinity,
              ),
            ),
          ),
        ),
      );
    }

    // ── Audio / Voice Note ─────────────────────────────────────────────────
    if (widget.message.type == "audio") {
      final totalSec = _audioDurationSeconds > 1 ? _audioDurationSeconds : _audioCurrentSeconds;
      final durationStr =
          '${(totalSec ~/ 60).toString().padLeft(1, '0')}:${(totalSec % 60).toString().padLeft(2, '0')}';

      return Container(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            CircleAvatar(
              radius: 18,
              backgroundColor: AppTheme.primary,
              child: IconButton(
                padding: EdgeInsets.zero,
                icon: Icon(
                  _isPlaying
                      ? Icons.pause_rounded
                      : Icons.play_arrow_rounded,
                  color: Colors.white,
                  size: 20,
                ),
                onPressed: () => _toggleAudioPlayback(base64Data),
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  SliderTheme(
                    data: SliderTheme.of(context).copyWith(
                      trackHeight: 2,
                      thumbShape:
                          const RoundSliderThumbShape(enabledThumbRadius: 5),
                      overlayShape:
                          const RoundSliderOverlayShape(overlayRadius: 10),
                      activeTrackColor: AppTheme.primary,
                      inactiveTrackColor:
                          AppTheme.textSecondary(context).withOpacity(0.3),
                      thumbColor: AppTheme.primary,
                      overlayColor: AppTheme.primary.withOpacity(0.2),
                    ),
                    child: Slider(
                      value: _audioProgress.clamp(0.0, 1.0),
                      onChanged: (v) async {
                        final targetMs =
                            (v * _audioDurationSeconds * 1000).toInt();
                        await _player
                            .seek(Duration(milliseconds: targetMs));
                      },
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(left: 4),
                    child: Text(
                      durationStr,
                      style: TextStyle(
                        color: AppTheme.textSecondary(context),
                        fontSize: 11,
                        fontFeatures: const [FontFeature.tabularFigures()],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      );
    }

    // ── Default: Document / File ───────────────────────────────────────────
    return Container(
      padding: const EdgeInsets.all(10),
      decoration: BoxDecoration(
        color: Colors.black.withOpacity(0.10),
        borderRadius: BorderRadius.circular(8),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 40,
            height: 40,
            decoration: BoxDecoration(
              color: AppTheme.primary.withOpacity(0.15),
              shape: BoxShape.circle,
            ),
            child: const Icon(Icons.insert_drive_file_rounded,
                color: AppTheme.primary, size: 22),
          ),
          const SizedBox(width: 10),
          Text(
            _getLabel(),
            style: TextStyle(
                color: AppTheme.textPrimary(context),
                fontWeight: FontWeight.w500,
                fontSize: 13),
          ),
        ],
      ),
    );
  }

  IconData _getIcon() {
    switch (widget.message.type) {
      case "image":
        return Icons.photo_camera_rounded;
      case "video":
        return Icons.videocam_rounded;
      case "audio":
        return Icons.mic_rounded;
      case "sticker":
        return Icons.emoji_emotions_rounded;
      default:
        return Icons.insert_drive_file_rounded;
    }
  }

  String _getLabel() {
    switch (widget.message.type) {
      case "image":
        return "Photo";
      case "video":
        return "Video";
      case "audio":
        return "Voice note";
      case "sticker":
        return "Sticker";
      default:
        return "File";
    }
  }
}
