import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:async';
import '../../models/image_filter.dart';
import '../../models/post.dart';
import '../../models/sojorn_media_result.dart';
import '../../models/tone_analysis.dart';
import '../../providers/api_provider.dart';
import '../../providers/feed_refresh_provider.dart';
import '../../services/api_service.dart';
import '../../services/image_upload_service.dart';
import '../../theme/app_theme.dart';
import '../../theme/tokens.dart';
import '../../widgets/composer/composer_toolbar.dart';
import '../../services/content_filter.dart';
import '../../widgets/sojorn_snackbar.dart';
import 'image_editor_screen.dart';
import '../quips/create/quip_studio_screen.dart'; // Added import
import '../quips/create/quip_editor_screen.dart'; // Added import

class ComposeScreen extends ConsumerStatefulWidget {
  final Post? chainParentPost;

  const ComposeScreen({super.key, this.chainParentPost});

  @override
  ConsumerState<ComposeScreen> createState() => _ComposeScreenState();
}

class _ComposeScreenState extends ConsumerState<ComposeScreen> {
  final _bodyController = TextEditingController();
  final _charCountNotifier = ValueNotifier<int>(0);
  final _bodyFocusNode = FocusNode();
  final ImageUploadService _imageUploadService = ImageUploadService();

  bool _isLoading = false;
  bool _isUploadingImage = false;
  bool _popped = false;
  String? _errorMessage;
  String? _blockedMessage;
  final int _maxCharacters = 500;
  bool _allowChain = true;
  bool _isNsfw = false;
  bool _isBold = false;
  bool _isItalic = false;
  int? _ttlHoursOverride;

  // Link preview state
  String? _detectedUrl;
  Map<String, dynamic>? _linkPreview;
  bool _isFetchingPreview = false;
  Timer? _urlDebounce;
  bool _isTyping = false;

  File? _selectedImageFile;
  Uint8List? _selectedImageBytes;
  String? _selectedImageName;
  ImageFilter? _selectedFilter;
  final ImagePicker _imagePicker = ImagePicker();
  static const double _editorFontSize = 18;
  List<String> _tagSuggestions = [];
  Timer? _hashtagDebounce;
  static const Map<int?, String> _ttlOptions = {
    null: 'Use default',
    0: 'Forever',
    12: '12 Hours',
    24: '24 Hours',
    72: '3 Days',
    168: '1 Week',
  };

  @override
  void initState() {
    super.initState();
    _allowChain = true;
    _bodyController.addListener(() {
      _charCountNotifier.value = _bodyController.text.length;
      _handleHashtagSuggestions();
      _handleUrlDetection();
      // Clear blocked banner when user edits their text
      if (_blockedMessage != null) {
        setState(() => _blockedMessage = null);
      }
    });
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!mounted) return;
      _bodyFocusNode.requestFocus();
    });
  }

  /// Detect URLs in text and fetch a preview after a pause in typing.
  void _handleUrlDetection() {
    setState(() => _isTyping = true);
    _urlDebounce?.cancel();
    _urlDebounce = Timer(const Duration(milliseconds: 800), () {
      if (!mounted) return;
      setState(() => _isTyping = false);
      final urlMatch = RegExp(r'https?://\S+').firstMatch(_bodyController.text);
      final url = urlMatch?.group(0);
      if (url != null && url != _detectedUrl && url.length > 10) {
        _detectedUrl = url;
        _fetchLinkPreview(url);
      } else if (url == null) {
        setState(() {
          _detectedUrl = null;
          _linkPreview = null;
        });
      }
    });
  }

  Future<void> _fetchLinkPreview(String url) async {
    if (_isFetchingPreview) return;
    setState(() => _isFetchingPreview = true);
    try {
      final data = await ApiService.instance.callGoApi(
        '/safe-domains/check',
        method: 'GET',
        queryParams: {'url': url},
      );
      if (!mounted) return;
      // Now fetch the OG preview from a lightweight endpoint
      // For now, just show the URL + safety status as a card
      setState(() {
        _linkPreview = {
          'url': url,
          'domain': data['domain'] ?? '',
          'safe': data['safe'] ?? false,
          'status': data['status'] ?? 'unknown',
        };
      });
    } catch (_) {
      // Silently fail - preview is optional
    }
    if (mounted) setState(() => _isFetchingPreview = false);
  }

  @override
  void dispose() {
    _urlDebounce?.cancel();
    _hashtagDebounce?.cancel();
    _charCountNotifier.dispose();
    _bodyFocusNode.dispose();
    _bodyController.dispose();
    super.dispose();
  }

  // Refactored _pickMedia to support Video > QuipEditorScreen flow
  Future<void> _pickMedia() async {
    final choice = await showModalBottomSheet<String>(
      context: context,
      backgroundColor: AppTheme.cardSurface,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (context) => SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ListTile(
              leading: Icon(Icons.image, color: AppTheme.navyBlue),
              title: const Text('Image'),
              onTap: () => Navigator.pop(context, 'image'),
            ),
            ListTile(
              leading: Icon(Icons.videocam, color: AppTheme.navyBlue),
              title: const Text('Video'),
              onTap: () => Navigator.pop(context, 'video'),
            ),
          ],
        ),
      ),
    );

    if (!mounted || choice == null) return;

    if (choice == 'image') {
      await _pickImage();
    } else if (choice == 'video') {
      // Direct Record-to-Edit flow: Route immediately to QuipEditorScreen
      if (kIsWeb) {
        sojornSnackbar.showError(
          context: context,
          message: 'Video editing is not supported on web yet',
        );
        return;
      }

      try {
        final XFile? pickedFile = await _imagePicker.pickVideo(
          source: ImageSource.gallery,
        );

        if (pickedFile != null && mounted) {
          // Navigate directly to QuipStudioScreen (ProVideoEditor)
          // Note: using QuipStudioScreen as defined in quip_studio_screen.dart
          final result = await Navigator.push<bool>(
            context,
            MaterialPageRoute(
              builder: (context) => QuipStudioScreen(
                videoFile: File(pickedFile.path),
              ),
            ),
          );

          // If video was posted successfully (returned true), close compose screen
          if (result == true && mounted) {
            Navigator.of(context).pop(true);
          }
        }
      } catch (e) {
        sojornSnackbar.showError(
          context: context,
          message: 'Failed to select video: ${e.toString()}',
        );
      }
    }
  }

  Future<void> _pickImage() async {
    try {
      final XFile? pickedFile = await _imagePicker.pickImage(
        source: ImageSource.gallery,
        maxWidth: 2048,
        maxHeight: 2048,
        imageQuality: 85,
      );

      if (pickedFile != null && mounted) {
        final pickedBytes = kIsWeb ? await pickedFile.readAsBytes() : null;
        if (kIsWeb && (pickedBytes == null || pickedBytes.isEmpty)) {
          sojornSnackbar.showError(
            context: context,
            message: 'Failed to load image bytes for web',
          );
          return;
        }
        final editorResult = await Navigator.push<SojornMediaResult>(
          context,
          MaterialPageRoute(
            builder: (context) => sojornImageEditor(
              imagePath: kIsWeb ? null : pickedFile.path,
              imageBytes: pickedBytes,
              imageName: pickedFile.name,
            ),
          ),
        );

        if (editorResult != null && mounted) {
          setState(() {
            _selectedImageFile = editorResult.filePath != null
                ? File(editorResult.filePath!)
                : null;
            _selectedImageBytes = editorResult.bytes;
            _selectedImageName = editorResult.name ?? pickedFile.name;
          });
        }
      }
    } catch (e) {
      sojornSnackbar.showError(
        context: context,
        message: 'Failed to select image: ${e.toString()}',
      );
    }
  }

  void _removeImage() {
    setState(() {
      _selectedImageFile = null;
      _selectedImageBytes = null;
      _selectedImageName = null;
      _selectedFilter = null;
    });
  }

  void _toggleBold() {
    setState(() {
      _isBold = !_isBold;
    });
  }

  void _toggleItalic() {
    setState(() {
      _isItalic = !_isItalic;
    });
  }

  void _toggleChain() {
    setState(() {
      _allowChain = !_allowChain;
    });
  }

  Future<void> _openTtlSelector() async {
    final choice = await showModalBottomSheet<_TtlChoice>(
      context: context,
      builder: (context) {
        return SafeArea(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: _ttlOptions.entries.map((entry) {
              final isSelected = entry.key == _ttlHoursOverride;
              return ListTile(
                title: Text(entry.value),
                trailing: isSelected
                    ? Icon(Icons.check, color: AppTheme.brightNavy)
                    : null,
                onTap: () => Navigator.pop(context, _TtlChoice(entry.key)),
              );
            }).toList(),
          ),
        );
      },
    );

    if (choice == null) return;
    setState(() => _ttlHoursOverride = choice.hours);
  }

  String? _activeHashtag() {
    final cursor = _bodyController.selection.baseOffset;
    if (cursor < 0 || cursor > _bodyController.text.length) return null;
    final prefix = _bodyController.text.substring(0, cursor);
    final match = RegExp(r'#([A-Za-z0-9_]{1,50})$').firstMatch(prefix);
    if (match != null) {
      return match.group(1)?.toLowerCase();
    }
    return null;
  }

  void _handleHashtagSuggestions() {
    final tag = _activeHashtag();
    _hashtagDebounce?.cancel();
    if (tag == null || tag.isEmpty) {
      setState(() => _tagSuggestions = []);
      return;
    }
    _hashtagDebounce = Timer(const Duration(milliseconds: 200), () async {
      try {
        final apiService = ref.read(apiServiceProvider);
        final results = await apiService.search(tag);
        final suggestions = results.tags
            .map((t) => t.tag.toLowerCase())
            .where((t) => t.startsWith(tag))
            .toSet()
            .toList();
        if (mounted) {
          setState(() {
            _tagSuggestions = suggestions;
          });
        }
      } catch (_) {
        if (mounted) setState(() => _tagSuggestions = []);
      }
    });
  }

  void _insertHashtag(String tag) {
    final cursor = _bodyController.selection.baseOffset;
    if (cursor < 0) return;
    final text = _bodyController.text;
    final prefix = text.substring(0, cursor);
    final suffix = text.substring(cursor);
    final match = RegExp(r'#([A-Za-z0-9_]{1,50})$').firstMatch(prefix);
    if (match == null) return;
    final start = match.start;
    final newText = prefix.substring(0, start) + '#$tag ' + suffix;
    _bodyController.value = TextEditingValue(
      text: newText,
      selection: TextSelection.collapsed(offset: start + tag.length + 2),
    );
    setState(() {
      _tagSuggestions = [];
    });
  }

  Future<void> _publish() async {
    if (_bodyController.text.trim().isEmpty) {
      sojornSnackbar.showError(
        context: context,
        message: 'Post cannot be empty',
      );
      return;
    }

    // Layer 0: Client-side hard blocklist — never even send to server
    final blockMessage = ContentFilter.instance.check(_bodyController.text.trim());
    if (blockMessage != null) {
      setState(() => _blockedMessage = blockMessage);
      return;
    }

    setState(() {
      _isLoading = true;
      _errorMessage = null;
    });

    try {
      String? imageUrl;

      if (_selectedImageFile != null || _selectedImageBytes != null) {
        setState(() {
          _isUploadingImage = true;
        });

        try {
          if (_selectedImageBytes != null) {
            imageUrl = await _imageUploadService.uploadImageBytes(
              _selectedImageBytes!,
              fileName: _selectedImageName,
              filter: _selectedFilter,
            );
          } else if (_selectedImageFile != null) {
            imageUrl = await _imageUploadService.uploadImage(
              _selectedImageFile!,
              filter: _selectedFilter,
            );
          }
        } catch (e) {
          throw Exception(
              'Image upload failed: ${e.toString().replaceAll('Exception: ', '')}');
        } finally {
          setState(() {
            _isUploadingImage = false;
          });
        }
      }

      final apiService = ref.read(apiServiceProvider);

      await apiService.publishPost(
        body: _bodyController.text.trim(),
        bodyFormat: 'plain',
        allowChain: _allowChain,
        chainParentId: widget.chainParentPost?.id,
        imageUrl: imageUrl,
        ttlHours: _ttlHoursOverride,
        isNsfw: _isNsfw,
      );

      if (mounted && !_popped) {
        _popped = true;
        ref.read(feedRefreshProvider.notifier).increment();
        Navigator.of(context).pop(true);
        return; // Skip finally setState — widget is being disposed
      }
    } catch (e) {
      if (!mounted || _popped) return;
      final msg = e.toString().replaceAll('Exception: ', '');
      // Server-side blocklist catch (422 with blocked content message)
      if (msg.contains("isn't allowed on Sojorn") || msg.contains('not allowed')) {
        setState(() => _blockedMessage = msg);
      } else {
        setState(() {
          _errorMessage = msg;
        });
      }
    } finally {
      if (mounted && !_popped) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  Future<bool> _showWarningDialog(ToneCheckResult analysis) async {
    final categoryLabel = analysis.categoryLabel;
    final message =
        'Hold on. Our system detected this may contain $categoryLabel content. '
        'If you post this and it violates our guidelines, you will receive a Strike.';

    final result = await showDialog<bool>(
      context: context,
      barrierDismissible: false,
      builder: (context) => AlertDialog(
        title: const Text('Hold on'),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: const Text('Edit'),
          ),
          ElevatedButton(
            onPressed: () => Navigator.pop(context, true),
            child: const Text('Post Anyway'),
          ),
        ],
      ),
    );

    return result ?? false;
  }

  Widget _buildBlockedBanner() {
    return AnimatedSize(
      duration: const Duration(milliseconds: 250),
      curve: Curves.easeOut,
      child: _blockedMessage != null
          ? Container(
              width: double.infinity,
              padding: const EdgeInsets.symmetric(
                horizontal: AppTheme.spacingMd,
                vertical: 12,
              ),
              decoration: BoxDecoration(
                color: const Color(0xFFFEF2F2),
                border: Border(
                  bottom: BorderSide(
                    color: AppTheme.error.withValues(alpha: 0.2),
                  ),
                ),
              ),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Icon(Icons.info_outline, color: AppTheme.error, size: 20),
                  const SizedBox(width: 10),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          _blockedMessage!,
                          style: AppTheme.textTheme.bodySmall?.copyWith(
                            color: const Color(0xFF991B1B),
                            fontWeight: FontWeight.w500,
                            height: 1.4,
                          ),
                        ),
                      ],
                    ),
                  ),
                  GestureDetector(
                    onTap: () => setState(() => _blockedMessage = null),
                    child: Padding(
                      padding: const EdgeInsets.only(left: 8),
                      child: Icon(
                        Icons.close,
                        size: 16,
                        color: AppTheme.error.withValues(alpha: 0.6),
                      ),
                    ),
                  ),
                ],
              ),
            )
          : const SizedBox.shrink(),
    );
  }

  bool get _canPublish {
    return _bodyController.text.trim().isNotEmpty &&
        _bodyController.text.trim().length <= _maxCharacters &&
        !_isLoading &&
        !_isUploadingImage;
  }

  @override
  Widget build(BuildContext context) {
    final bool isKeyboardOpen = MediaQuery.of(context).viewInsets.bottom > 0;
    return Scaffold(
      backgroundColor: AppTheme.scaffoldBg,
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(52),
        child: ValueListenableBuilder<int>(
          valueListenable: _charCountNotifier,
          builder: (_, __, ___) => ComposeAppBar(
            isLoading: _isLoading,
            canPublish: _canPublish,
            postAction: _publish,
            replyTitle: widget.chainParentPost != null 
                ? 'Reply to ${widget.chainParentPost!.author?.displayName ?? 'Anonymous'}'
                : null,
          ),
        ),
      ),
      body: SafeArea(
        child: Column(
          children: [
            _buildBlockedBanner(),
            if (_errorMessage != null)
              Container(
                width: double.infinity,
                padding: const EdgeInsets.symmetric(
                  horizontal: AppTheme.spacingMd,
                  vertical: AppTheme.spacingSm,
                ),
                color: AppTheme.error.withValues(alpha: 0.08),
                child: Text(
                  _errorMessage!,
                  style: AppTheme.textTheme.labelSmall?.copyWith(
                    color: AppTheme.error,
                  ),
                ),
              ),
            // Reply context indicator
            if (widget.chainParentPost != null)
              Container(
                width: double.infinity,
                padding: const EdgeInsets.symmetric(
                  horizontal: AppTheme.spacingMd,
                  vertical: AppTheme.spacingSm,
                ),
                margin: const EdgeInsets.only(bottom: AppTheme.spacingSm),
                decoration: BoxDecoration(
                  color: AppTheme.navyBlue.withValues(alpha: 0.05),
                  borderRadius: BorderRadius.circular(8),
                  border: Border.all(
                    color: AppTheme.navyBlue.withValues(alpha: 0.2),
                    width: 1,
                  ),
                ),
                child: Row(
                  children: [
                    Icon(
                      Icons.reply,
                      size: 16,
                      color: AppTheme.navyBlue,
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: Text(
                        'Replying to ${widget.chainParentPost!.author?.displayName ?? 'Anonymous'}',
                        style: AppTheme.labelSmall?.copyWith(
                          color: AppTheme.navyBlue,
                          fontWeight: FontWeight.w500,
                        ),
                        overflow: TextOverflow.ellipsis,
                      ),
                    ),
                  ],
                ),
              ),
            Expanded(
              child: ComposeBody(
                controller: _bodyController,
                focusNode: _bodyFocusNode,
                isBold: _isBold,
                isItalic: _isItalic,
                suggestions: _tagSuggestions,
                onSelectSuggestion: _insertHashtag,
                imageWidget: (_selectedImageFile != null ||
                            _selectedImageBytes != null) &&
                        !isKeyboardOpen
                    ? _buildImagePreview()
                    : null,
                linkPreviewWidget: !_isTyping && _linkPreview != null && !isKeyboardOpen
                    ? _buildComposeLinkPreview()
                    : null,
              ),
            ),
          ],
        ),
      ),
      bottomNavigationBar: ValueListenableBuilder<int>(
        valueListenable: _charCountNotifier,
        builder: (_, count, __) {
          final remaining = _maxCharacters - count;
          return AnimatedPadding(
            duration: const Duration(milliseconds: 150),
            padding: EdgeInsets.only(
                bottom: MediaQuery.of(context).viewInsets.bottom),
            child: ComposeBottomBar(
              onAddMedia: _pickMedia,
              onToggleBold: _toggleBold,
              onToggleItalic: _toggleItalic,
              onToggleChain: _toggleChain,
              onToggleNsfw: () => setState(() => _isNsfw = !_isNsfw),
              onSelectTtl: _openTtlSelector,
              ttlOverrideActive: _ttlHoursOverride != null,
              ttlLabel: _ttlOptions[_ttlHoursOverride] ?? 'Use default',
              isBold: _isBold,
              isItalic: _isItalic,
              allowChain: _allowChain,
              isNsfw: _isNsfw,
              characterCount: count,
              maxCharacters: _maxCharacters,
              isUploadingImage: _isUploadingImage,
              remainingChars: remaining,
            ),
          );
        },
      ),
    );
  }

  Widget _buildImagePreview() {
    return Padding(
      padding: const EdgeInsets.symmetric(
          horizontal: AppTheme.spacingLg, vertical: AppTheme.spacingSm),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(12),
        child: Stack(
          children: [
            AspectRatio(
              aspectRatio: 4 / 3,
              child: _selectedImageBytes != null
                  ? Image.memory(
                      _selectedImageBytes!,
                      width: double.infinity,
                      fit: BoxFit.cover,
                    )
                  : Image.file(
                      _selectedImageFile!,
                      width: double.infinity,
                      fit: BoxFit.cover,
                    ),
            ),
            Positioned(
              top: 8,
              right: 8,
              child: Material(
                color: SojornColors.overlayDark,
                shape: const CircleBorder(),
                child: InkWell(
                  onTap: _removeImage,
                  customBorder: const CircleBorder(),
                  child: const Padding(
                    padding: EdgeInsets.all(6),
                    child: Icon(Icons.close, color: SojornColors.basicWhite, size: 18),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildComposeLinkPreview() {
    final preview = _linkPreview!;
    final domain = preview['domain'] as String? ?? '';
    final url = preview['url'] as String? ?? '';
    final isSafe = preview['safe'] as bool? ?? false;

    return Container(
      margin: const EdgeInsets.symmetric(horizontal: AppTheme.spacingLg, vertical: 8),
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: isSafe
            ? AppTheme.navyBlue.withValues(alpha: 0.05)
            : SojornColors.nsfwWarningBg,
        borderRadius: BorderRadius.circular(12),
        border: Border.all(
          color: isSafe
              ? AppTheme.navyBlue.withValues(alpha: 0.15)
              : SojornColors.nsfwWarningBorder,
        ),
      ),
      child: Row(
        children: [
          Icon(
            isSafe ? Icons.link_rounded : Icons.warning_amber_rounded,
            size: 20,
            color: isSafe ? AppTheme.navyBlue : AppTheme.nsfwWarningIcon,
          ),
          const SizedBox(width: 10),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  domain.toUpperCase(),
                  style: TextStyle(
                    fontSize: 10,
                    fontWeight: FontWeight.w700,
                    letterSpacing: 0.8,
                    color: AppTheme.textTertiary,
                  ),
                ),
                const SizedBox(height: 2),
                Text(
                  url.length > 60 ? '${url.substring(0, 57)}...' : url,
                  style: TextStyle(
                    fontSize: 12,
                    color: AppTheme.textSecondary,
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
          if (_isFetchingPreview)
            const SizedBox(
              width: 16, height: 16,
              child: CircularProgressIndicator(strokeWidth: 2),
            )
          else
            GestureDetector(
              onTap: () => setState(() {
                _linkPreview = null;
                _detectedUrl = null;
              }),
              child: Icon(Icons.close, size: 18, color: AppTheme.textTertiary),
            ),
        ],
      ),
    );
  }
}

/// Minimal top bar with Cancel + Post pill
class ComposeAppBar extends StatelessWidget {
  final bool isLoading;
  final bool canPublish;
  final VoidCallback postAction;
  final String? replyTitle;

  const ComposeAppBar({
    super.key,
    required this.isLoading,
    required this.canPublish,
    required this.postAction,
    this.replyTitle,
  });

  @override
  Widget build(BuildContext context) {
    final bool disabled = !canPublish || isLoading;
    return AppBar(
      elevation: 0,
      backgroundColor: AppTheme.scaffoldBg,
      leadingWidth: 80,
      leading: TextButton(
        onPressed: isLoading ? null : () => Navigator.of(context).pop(),
        child: Text(
          'Cancel',
          style: TextStyle(
            color: AppTheme.egyptianBlue,
            fontWeight: FontWeight.w600,
          ),
        ),
      ),
      title: replyTitle != null 
        ? Text(
            replyTitle!,
            style: AppTheme.labelSmall?.copyWith(
              color: AppTheme.navyText,
              fontSize: 14,
            ),
          )
        : const SizedBox.shrink(),
      actions: [
        Padding(
          padding: const EdgeInsets.only(right: AppTheme.spacingMd),
          child: AnimatedOpacity(
            duration: const Duration(milliseconds: 150),
            opacity: disabled ? 0.5 : 1.0,
            child: ElevatedButton(
              onPressed: disabled ? null : postAction,
              style: ElevatedButton.styleFrom(
                backgroundColor: AppTheme.brightNavy,
                foregroundColor: AppTheme.white,
                elevation: 0,
                padding:
                    const EdgeInsets.symmetric(horizontal: 18, vertical: 10),
                shape: const StadiumBorder(),
              ),
              child: isLoading
                  ? const SizedBox(
                      width: 16,
                      height: 16,
                      child: CircularProgressIndicator(
                        strokeWidth: 2,
                        color: AppTheme.white,
                      ),
                    )
                  : const Text(
                      'Post',
                      style: TextStyle(
                        fontWeight: FontWeight.w700,
                        fontSize: 15,
                      ),
                    ),
            ),
          ),
        ),
      ],
    );
  }
}

/// Body with immersive canvas and optional media preview
class ComposeBody extends StatelessWidget {
  final TextEditingController controller;
  final FocusNode focusNode;
  final bool isBold;
  final bool isItalic;
  final Widget? imageWidget;
  final Widget? linkPreviewWidget;
  final List<String> suggestions;
  final ValueChanged<String> onSelectSuggestion;

  const ComposeBody({
    super.key,
    required this.controller,
    required this.focusNode,
    required this.isBold,
    required this.isItalic,
    required this.suggestions,
    required this.onSelectSuggestion,
    this.imageWidget,
    this.linkPreviewWidget,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: Padding(
            padding: const EdgeInsets.symmetric(
              horizontal: AppTheme.spacingLg,
              vertical: AppTheme.spacingMd,
            ),
            child: Column(
              children: [
                Expanded(
                  child: TextField(
                    controller: controller,
                    focusNode: focusNode,
                    autofocus: true,
                    maxLines: null,
                    minLines: null,
                    expands: true,
                    keyboardType: TextInputType.multiline,
                    textInputAction: TextInputAction.newline,
                    textAlignVertical: TextAlignVertical.top,
                    style: AppTheme.textTheme.bodyLarge?.copyWith(
                      fontSize: _ComposeScreenState._editorFontSize,
                      height: 1.5,
                      fontWeight: isBold ? FontWeight.w700 : FontWeight.w400,
                      fontStyle: isItalic ? FontStyle.italic : FontStyle.normal,
                    ),
                    decoration: const InputDecoration(
                      hintText: "What's happening?",
                      border: InputBorder.none,
                      isCollapsed: true,
                    ),
                    cursorColor: AppTheme.brightNavy,
                  ),
                ),
                if (suggestions.isNotEmpty)
                  Container(
                    width: double.infinity,
                    margin: const EdgeInsets.only(top: 8),
                    decoration: BoxDecoration(
                      color: AppTheme.cardSurface,
                      borderRadius: BorderRadius.circular(12),
                      boxShadow: [
                        BoxShadow(
                          color: SojornColors.overlayScrim,
                          blurRadius: 8,
                          offset: const Offset(0, 2),
                        ),
                      ],
                    ),
                    child: ListView.separated(
                      shrinkWrap: true,
                      itemCount: suggestions.length,
                      separatorBuilder: (_, __) => const Divider(height: 1),
                      itemBuilder: (context, index) {
                        final tag = suggestions[index];
                        return ListTile(
                          title: Text('#$tag', style: AppTheme.bodyMedium),
                          onTap: () => onSelectSuggestion(tag),
                        );
                      },
                    ),
                  ),
              ],
            ),
          ),
        ),
        if (linkPreviewWidget != null) linkPreviewWidget!,
        if (imageWidget != null) imageWidget!,
      ],
    );
  }
}

/// Bottom bar pinned above the keyboard with formatting + counter
class ComposeBottomBar extends StatelessWidget {
  final VoidCallback onAddMedia;
  final VoidCallback onToggleBold;
  final VoidCallback onToggleItalic;
  final VoidCallback onToggleChain;
  final VoidCallback? onToggleNsfw;
  final VoidCallback onSelectTtl;
  final bool isBold;
  final bool isItalic;
  final bool allowChain;
  final bool isNsfw;
  final bool ttlOverrideActive;
  final String ttlLabel;
  final int characterCount;
  final int maxCharacters;
  final bool isUploadingImage;
  final int remainingChars;

  const ComposeBottomBar({
    super.key,
    required this.onAddMedia,
    required this.onToggleBold,
    required this.onToggleItalic,
    required this.onToggleChain,
    this.onToggleNsfw,
    required this.onSelectTtl,
    required this.ttlOverrideActive,
    required this.ttlLabel,
    required this.isBold,
    required this.isItalic,
    required this.allowChain,
    this.isNsfw = false,
    required this.characterCount,
    required this.maxCharacters,
    required this.isUploadingImage,
    required this.remainingChars,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: AppTheme.cardSurface,
        border: Border(
          top: BorderSide(
            color: AppTheme.egyptianBlue.withValues(alpha: 0.12),
          ),
        ),
      ),
      padding: const EdgeInsets.symmetric(
        horizontal: AppTheme.spacingMd,
        vertical: AppTheme.spacingSm,
      ),
      child: SafeArea(
        top: false,
        child: ComposerToolbar(
          onAddMedia: onAddMedia,
          onToggleBold: onToggleBold,
          onToggleItalic: onToggleItalic,
          onToggleChain: onToggleChain,
          onToggleNsfw: onToggleNsfw,
          onSelectTtl: onSelectTtl,
          ttlOverrideActive: ttlOverrideActive,
          ttlLabel: ttlLabel,
          isBold: isBold,
          isItalic: isItalic,
          allowChain: allowChain,
          isNsfw: isNsfw,
          characterCount: characterCount,
          maxCharacters: maxCharacters,
          isUploadingImage: isUploadingImage,
          remainingChars: remainingChars,
        ),
      ),
    );
  }
}

class _TtlChoice {
  final int? hours;
  const _TtlChoice(this.hours);
}
