part of '../rooms_panel.dart';

class _DraggableRoomItem extends StatefulWidget {
  final Room room;
  final int index;
  final bool isActive;
  final bool isInVoice;
  final PyramidTheme pt;
  final VoidCallback onTap;
  const _DraggableRoomItem({
    super.key,
    required this.room,
    required this.index,
    required this.isActive,
    this.isInVoice = false,
    required this.pt,
    required this.onTap,
  });

  @override
  State<_DraggableRoomItem> createState() => _DraggableRoomItemState();
}

class _DraggableRoomItemState extends State<_DraggableRoomItem> {
  bool _hovered = false;

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      onEnter: (_) => setState(() => _hovered = true),
      onExit: (_) => setState(() => _hovered = false),
      child: Row(children: [
        ReorderableDragStartListener(
          index: widget.index,
          child: MouseRegion(
            cursor: SystemMouseCursors.grab,
            child: AnimatedOpacity(
              opacity: _hovered ? 1.0 : 0.0,
              duration: const Duration(milliseconds: 120),
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 3),
                child: Icon(Icons.drag_indicator_rounded,
                    size: 12, color: widget.pt.fgDim),
              ),
            ),
          ),
        ),
        Expanded(
          child: _RoomItem(
            room: widget.room,
            isActive: widget.isActive,
            isInVoice: widget.isInVoice,
            pt: widget.pt,
            onTap: widget.onTap,
          ),
        ),
      ]),
    );
  }
}

class _RoomsList extends ConsumerWidget {
  final List<Room> rooms;
  final String filter;
  final String? spaceId;
  final Map<String, bool> collapsed;
  final PyramidTheme pt;
  final ValueChanged<String> onToggleSection;

  const _RoomsList({
    required this.rooms,
    required this.filter,
    required this.spaceId,
    required this.collapsed,
    required this.pt,
    required this.onToggleSection,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final activeRoomId = ref.watch(activeRoomIdProvider);
    final isDms = spaceId == 'dms';

    final invites = rooms
        .where((r) =>
            r.membership == Membership.invite &&
            isDms == r.isDirectChat)
        .toList();

    final filtered = rooms.where((r) {
      if (r.membership == Membership.invite) return false;
      if (isDms != r.isDirectChat) return false;
      if (filter.isEmpty) return true;
      return r.getLocalizedDisplayname()
          .toLowerCase()
          .contains(filter.toLowerCase());
    }).toList();

    if (filtered.isEmpty && invites.isEmpty) {
      return Center(
          child:
              Text('No rooms', style: TextStyle(color: pt.fgDim, fontSize: 13)));
    }

    final sectionTitle = isDms ? 'Direct Messages' : 'Rooms';
    final sectionId = isDms ? 'dms' : 'rooms';
    final isCollapsed = collapsed[sectionId] ?? false;

    return ListView(
      padding: const EdgeInsets.fromLTRB(8, 4, 8, 12),
      children: [
        if (invites.isNotEmpty) ...[
          Padding(
            padding: const EdgeInsets.fromLTRB(8, 6, 8, 2),
            child: Text('EINLADUNGEN',
                style: TextStyle(
                    color: pt.accent,
                    fontSize: 10,
                    fontWeight: FontWeight.w700,
                    letterSpacing: 0.6)),
          ),
          ...invites.map((r) => Padding(
              padding: const EdgeInsets.symmetric(vertical: 2),
              child: _InviteItem(room: r, pt: pt))),
          const SizedBox(height: 4),
        ],
        _SectionHeader(
          title: sectionTitle,
          count: filtered.length,
          isCollapsed: isCollapsed,
          pt: pt,
          onToggle: () => onToggleSection(sectionId),
          onAddTap: isDms
              ? () => showDialog(
                  context: context, builder: (_) => const NewDmDialog())
              : () => showDialog(
                  context: context, builder: (_) => const CreateJoinDialog()),
        ),
        if (!isCollapsed)
          ...filtered.map((room) => _RoomItem(
                room: room,
                isActive: activeRoomId == room.id,
                pt: pt,
                onTap: () {
                  ref.read(activeRoomIdProvider.notifier).state = room.id;
                  ref.read(viewModeProvider.notifier).state = ViewMode.chat;
                },
              )),
      ],
    );
  }
}

class _SectionHeader extends StatefulWidget {
  final String title;
  final int count;
  final bool isCollapsed;
  final PyramidTheme pt;
  final VoidCallback onToggle;
  final VoidCallback? onAddTap;

  const _SectionHeader({
    required this.title,
    required this.count,
    required this.isCollapsed,
    required this.pt,
    required this.onToggle,
    this.onAddTap,
  });

  @override
  State<_SectionHeader> createState() => _SectionHeaderState();
}

class _SectionHeaderState extends State<_SectionHeader> {
  bool _hovered = false;

  @override
  Widget build(BuildContext context) {
    final pt = widget.pt;
    return MouseRegion(
      onEnter: (_) => setState(() => _hovered = true),
      onExit: (_) => setState(() => _hovered = false),
      child: Container(
        padding: const EdgeInsets.fromLTRB(8, 6, 8, 4),
        child: Row(children: [
          Expanded(
            child: GestureDetector(
              onTap: widget.onToggle,
              child: Row(children: [
                AnimatedRotation(
                  turns: widget.isCollapsed ? -0.25 : 0,
                  duration: const Duration(milliseconds: 200),
                  curve: Curves.easeOutBack,
                  child: Icon(Icons.keyboard_arrow_down_rounded,
                      size: 14,
                      color: _hovered ? pt.fgMuted : pt.fgDim),
                ),
                const SizedBox(width: 4),
                Text(widget.title.toUpperCase(),
                    style: TextStyle(
                        color: _hovered ? pt.fgMuted : pt.fgDim,
                        fontSize: 11,
                        fontWeight: FontWeight.w600,
                        letterSpacing: 0.04 * 11)),
                const Spacer(),
                Text('${widget.count}',
                    style: TextStyle(color: pt.fgDim, fontSize: 11)),
              ]),
            ),
          ),
          if (_hovered && widget.onAddTap != null) ...[
            const SizedBox(width: 4),
            GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: widget.onAddTap,
              child: SizedBox(
                width: 18,
                height: 18,
                child: Center(
                    child: Icon(Icons.add, size: 12, color: pt.fgMuted)),
              ),
            ),
          ] else
            const SizedBox(width: 22),
        ]),
      ),
    );
  }
}

class _RoomItem extends ConsumerStatefulWidget {
  final Room room;
  final bool isActive;
  final bool isInVoice;
  final PyramidTheme pt;
  final VoidCallback onTap;

  const _RoomItem({
    super.key,
    required this.room,
    required this.isActive,
    this.isInVoice = false,
    required this.pt,
    required this.onTap,
  });

  @override
  ConsumerState<_RoomItem> createState() => _RoomItemState();
}

class _RoomItemState extends ConsumerState<_RoomItem> {
  bool _hovered = false;

  Future<void> _leaveRoom() async {
    final pt = widget.pt;
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        backgroundColor: pt.bg2,
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(pt.rXl),
            side: BorderSide(color: pt.border)),
        title: Text('Raum verlassen?',
            style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)),
        content: Text(
            '"${widget.room.getLocalizedDisplayname()}" verlassen?',
            style: TextStyle(color: pt.fgMuted, fontSize: 13)),
        actions: [
          TextButton(
              onPressed: () => Navigator.pop(ctx, false),
              child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))),
          ElevatedButton(
            style: ElevatedButton.styleFrom(
                backgroundColor: pt.danger,
                foregroundColor: Colors.white,
                elevation: 0,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8))),
            onPressed: () => Navigator.pop(ctx, true),
            child: const Text('Verlassen'),
          ),
        ],
      ),
    );
    if (confirmed != true || !mounted) return;
    try {
      final id = widget.room.id;
      await widget.room.leave();
      if (mounted && ref.read(activeRoomIdProvider) == id) {
        ref.read(activeRoomIdProvider.notifier).state = null;
      }
    } catch (_) {}
  }

  Future<void> _leaveDm() async {
    final pt = widget.pt;
    final confirmed = await showDialog<bool>(
      context: context,
      builder: (ctx) => AlertDialog(
        backgroundColor: pt.bg2,
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(pt.rXl),
            side: BorderSide(color: pt.border)),
        title: Text('Chat verlassen?',
            style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)),
        content: Text(
            'Unterhaltung mit "${widget.room.getLocalizedDisplayname()}" schließen?',
            style: TextStyle(color: pt.fgMuted, fontSize: 13)),
        actions: [
          TextButton(
              onPressed: () => Navigator.pop(ctx, false),
              child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))),
          ElevatedButton(
            style: ElevatedButton.styleFrom(
                backgroundColor: pt.danger,
                foregroundColor: Colors.white,
                elevation: 0,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8))),
            onPressed: () => Navigator.pop(ctx, true),
            child: const Text('Verlassen'),
          ),
        ],
      ),
    );
    if (confirmed != true || !mounted) return;
    try {
      final id = widget.room.id;
      await widget.room.leave();
      if (mounted) {
        if (ref.read(activeRoomIdProvider) == id) {
          ref.read(activeRoomIdProvider.notifier).state = null;
        }
      }
    } catch (_) {}
  }

  Future<void> _showRoomSettings() async {
    await showDialog(
      context: context,
      builder: (_) => RoomSettingsDialog(room: widget.room),
    );
  }

  Future<void> _inviteUser() async {
    final pt = widget.pt;
    final ctrl = TextEditingController();
    final userId = await showDialog<String>(
      context: context,
      builder: (ctx) => AlertDialog(
        backgroundColor: pt.bg2,
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(pt.rXl),
            side: BorderSide(color: pt.border)),
        title: Text('Nutzer einladen',
            style: TextStyle(
                color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)),
        content: TextField(
          controller: ctrl,
          autofocus: true,
          style: TextStyle(color: pt.fg, fontSize: 13),
          decoration: InputDecoration(
            hintText: '@nutzer:server',
            hintStyle: TextStyle(color: pt.fgDim, fontSize: 12),
            filled: true,
            fillColor: pt.bg3,
            isDense: true,
            border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide(color: pt.border)),
            enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide(color: pt.border)),
            focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(8),
                borderSide: BorderSide(color: pt.accent)),
          ),
          cursorColor: pt.accent,
          onSubmitted: (v) => Navigator.pop(ctx, v.trim()),
        ),
        actions: [
          TextButton(
              onPressed: () => Navigator.pop(ctx),
              child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))),
          TextButton(
              onPressed: () => Navigator.pop(ctx, ctrl.text.trim()),
              child: Text('Einladen', style: TextStyle(color: pt.accent))),
        ],
      ),
    );
    ctrl.dispose();
    if (userId == null || userId.isEmpty || !mounted) return;
    try {
      await widget.room.invite(userId);
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('Fehler: ${e.toString().split('\n').first}'),
          backgroundColor: widget.pt.danger,
        ));
      }
    }
  }

  /// Touch-friendly action menu — opened via long-press (the hover menu is not
  /// reachable on touch devices).
  void _showContextMenu() {
    final pt = widget.pt;
    final room = widget.room;
    final isDm = room.isDirectChat;

    Widget action(IconData icon, String label, VoidCallback onTap,
        {bool danger = false}) {
      return ListTile(
        leading: Icon(icon, size: 20, color: danger ? pt.danger : pt.fgMuted),
        title: Text(label,
            style: TextStyle(
                color: danger ? pt.danger : pt.fg, fontSize: 14)),
        onTap: () {
          Navigator.pop(context);
          onTap();
        },
      );
    }

    showModalBottomSheet(
      context: context,
      backgroundColor: pt.bg2,
      shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
      builder: (ctx) => SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(20, 16, 20, 8),
              child: Row(children: [
                Expanded(
                  child: Text(room.getLocalizedDisplayname(),
                      style: TextStyle(
                          color: pt.fg,
                          fontSize: 15,
                          fontWeight: FontWeight.w700),
                      overflow: TextOverflow.ellipsis),
                ),
              ]),
            ),
            Divider(height: 1, color: pt.border),
            if (!isDm) ...[
              action(Icons.person_add_outlined, 'Nutzer einladen', _inviteUser),
              action(Icons.settings_rounded, 'Einstellungen', _showRoomSettings),
            ],
            action(
              Icons.exit_to_app_rounded,
              isDm ? 'Chat verlassen' : 'Raum verlassen',
              isDm ? _leaveDm : _leaveRoom,
              danger: true,
            ),
            const SizedBox(height: 8),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final pt = widget.pt;
    final room = widget.room;
    final active = widget.isActive;
    final inVoice = widget.isInVoice;
    final name = room.getLocalizedDisplayname();
    final unread = room.notificationCount;
    final isDm = room.isDirectChat;
    final isVoice = _isVoiceRoom(room);
    final voiceParticipants = isVoice ? ref.watch(voiceParticipantsProvider(room.id)) : <Map<String, dynamic>>[];
    final client = ref.watch(matrixClientProvider).valueOrNull;

    Color textColor = (active || inVoice || unread > 0 || _hovered) ? pt.fg : pt.fgMuted;

    return MouseRegion(
      cursor: SystemMouseCursors.click,
      onEnter: (_) => setState(() => _hovered = true),
      onExit: (_) => setState(() => _hovered = false),
      child: GestureDetector(
        onTap: widget.onTap,
        onLongPress: _showContextMenu,
        child: Stack(
          children: [
            if (active)
              Positioned(
                left: 0,
                top: 6,
                bottom: 6,
                child: Container(
                  width: 3,
                  decoration: BoxDecoration(
                    color: pt.accent,
                    borderRadius: const BorderRadius.only(
                      topRight: Radius.circular(2),
                      bottomRight: Radius.circular(2),
                    ),
                  ),
                ),
              ),
            AnimatedContainer(
              duration: const Duration(milliseconds: 150),
              curve: Curves.easeOutCubic,
              margin: const EdgeInsets.symmetric(vertical: 1),
              padding: EdgeInsets.symmetric(
                  horizontal: pt.rowPadX, vertical: pt.rowPadY),
              decoration: BoxDecoration(
                color: active
                    ? pt.accentSoft
                    : inVoice
                        ? const Color(0xFF57F287).withAlpha(25)
                        : _hovered ? pt.bgHover : Colors.transparent,
                borderRadius: BorderRadius.circular(pt.rSm),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  Row(
                    children: [
                      if (isDm) ...[
                        _DmAvatar(room: room, pt: pt),
                      ] else ...[
                        SizedBox(
                          width: 16,
                          height: 16,
                          child: Icon(
                            isVoice ? Icons.mic_rounded : _roomIcon(room),
                            size: 14,
                            color: isVoice
                                ? (inVoice ? const Color(0xFF57F287) : _hovered ? const Color(0xFF57F287) : const Color(0xFF57F287).withAlpha(180))
                                : (active ? pt.accent : _hovered ? pt.fg : pt.fgDim),
                          ),
                        ),
                      ],
                      const SizedBox(width: 8),
                      Expanded(
                        child: Text(
                          name,
                          style: TextStyle(
                            color: textColor,
                            fontSize: 14,
                            fontWeight: unread > 0 || active || inVoice
                                ? FontWeight.w600
                                : FontWeight.w500,
                          ),
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                      if (isVoice && voiceParticipants.isNotEmpty)
                        Padding(
                          padding: const EdgeInsets.only(right: 4),
                          child: Text(
                            '${voiceParticipants.length}',
                            style: TextStyle(
                                color: const Color(0xFF57F287).withAlpha(200),
                                fontSize: 11,
                                fontWeight: FontWeight.w600),
                          ),
                        ),
                      if (!isVoice && _hovered) ...[
                        if (isDm)
                          _HoverAction(icon: Icons.close, pt: pt, onTap: _leaveDm)
                        else
                          _RoomMenuBtn(
                            pt: pt,
                            onInvite: _inviteUser,
                            onSettings: _showRoomSettings,
                            onLeave: _leaveRoom,
                          ),
                      ] else if (!isVoice && unread > 0) ...[
                        _UnreadBadge(
                            count: unread,
                            isMention: room.highlightCount > 0,
                            pt: pt),
                      ],
                    ],
                  ),
                  // Voice participants (Discord-style named rows)
                  if (isVoice && voiceParticipants.isNotEmpty)
                    Padding(
                      padding: const EdgeInsets.only(top: 2, left: 24),
                      child: _VoiceParticipantList(
                        participants: voiceParticipants,
                        client: client,
                        pt: pt,
                      ),
                    ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  IconData _roomIcon(Room room) {
    if (room.encrypted) return Icons.lock_outline_rounded;
    return Icons.tag_rounded;
  }
}
