import 'dart:async';

import 'package:flutter/material.dart' hide Visibility;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:matrix/matrix.dart';
import 'package:pyramid/core/app_state.dart';
import 'package:pyramid/core/matrix_client.dart';
import 'package:pyramid/core/theme.dart';
import 'package:pyramid/widgets/mxc_image.dart';

enum CreateJoinTab { create, join, discover }
enum _CreateType { room, voice, space }

class CreateJoinDialog extends ConsumerStatefulWidget {
  final CreateJoinTab initialTab;
  const CreateJoinDialog({super.key, this.initialTab = CreateJoinTab.create});

  @override
  ConsumerState<CreateJoinDialog> createState() => _CreateJoinDialogState();
}

class _CreateJoinDialogState extends ConsumerState<CreateJoinDialog> {
  late CreateJoinTab _tab;
  _CreateType _createType = _CreateType.room;

  // Create
  final _nameCtrl = TextEditingController();
  final _topicCtrl = TextEditingController();
  final _aliasCtrl = TextEditingController();
  bool _isPublic = false;
  bool _isEncrypted = true;
  bool _creating = false;
  String? _createError;

  // Join
  final _joinCtrl = TextEditingController();
  bool _joining = false;
  String? _joinError;

  // Discover
  final _discoverServerCtrl = TextEditingController();
  final _discoverSearchCtrl = TextEditingController();
  List<PublishedRoomsChunk> _publicRooms = [];
  String? _nextBatch;
  bool _discoverLoading = false;
  bool _discoverLoadingMore = false;
  String? _discoverError;
  Timer? _searchDebounce;
  final Set<String> _joiningRooms = {};

  @override
  void initState() {
    super.initState();
    _tab = widget.initialTab;
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_tab == CreateJoinTab.discover) _discover();
    });
  }

  @override
  void dispose() {
    _nameCtrl.dispose();
    _topicCtrl.dispose();
    _aliasCtrl.dispose();
    _joinCtrl.dispose();
    _discoverServerCtrl.dispose();
    _discoverSearchCtrl.dispose();
    _searchDebounce?.cancel();
    super.dispose();
  }

  Future<void> _create() async {
    final name = _nameCtrl.text.trim();
    if (name.isEmpty) {
      setState(() => _createError = 'Bitte einen Namen eingeben.');
      return;
    }
    setState(() { _creating = true; _createError = null; });
    try {
      final client = await ref.read(matrixClientProvider.future);
      String roomId;
      if (_createType == _CreateType.space) {
        roomId = await client.createSpace(
          name: name,
          topic: _topicCtrl.text.trim().isEmpty ? null : _topicCtrl.text.trim(),
          visibility: _isPublic ? Visibility.public : Visibility.private,
          spaceAliasName: _aliasCtrl.text.trim().isEmpty ? null : _aliasCtrl.text.trim(),
        );
      } else if (_createType == _CreateType.voice) {
        roomId = await client.createRoom(
          name: name,
          topic: _topicCtrl.text.trim().isEmpty ? null : _topicCtrl.text.trim(),
          visibility: Visibility.private,
          preset: CreateRoomPreset.privateChat,
          creationContent: {'type': 'io.pyramid.voice_channel'},
        );
        // Voice-Presence (io.pyramid.voice.presence) muss von JEDEM Mitglied
        // schreibbar sein (state_default ist 50, normale Mitglieder haben 0) —
        // sonst sieht man nur den Raum-Ersteller im Kanal. Nachträglich setzen,
        // weil Continuwuity power_level_content_override beim createRoom
        // ignoriert.
        try {
          final plRaw = await client.getRoomStateWithKey(
              roomId, EventTypes.RoomPowerLevels, '');
          final pl = Map<String, dynamic>.from(plRaw);
          final events =
              Map<String, dynamic>.from(pl['events'] as Map? ?? {});
          events['io.pyramid.voice.presence'] = 0;
          pl['events'] = events;
          await client.setRoomStateWithKey(
              roomId, EventTypes.RoomPowerLevels, '', pl);
        } catch (_) {
          // Nicht kritisch — Presence-Anzeige funktioniert dann nur für Admins.
        }
      } else {
        roomId = await client.createRoom(
          name: name,
          topic: _topicCtrl.text.trim().isEmpty ? null : _topicCtrl.text.trim(),
          visibility: _isPublic ? Visibility.public : Visibility.private,
          roomAliasName: _aliasCtrl.text.trim().isEmpty ? null : _aliasCtrl.text.trim(),
          preset: _isPublic ? CreateRoomPreset.publicChat : CreateRoomPreset.privateChat,
          initialState: _isEncrypted && !_isPublic
              ? [StateEvent(content: {'algorithm': 'm.megolm.v1.aes-sha2'}, type: EventTypes.Encryption)]
              : null,
        );
      }
      if (mounted) {
        ref.read(activeRoomIdProvider.notifier).state = roomId;
        ref.read(viewModeProvider.notifier).state = ViewMode.chat;
        Navigator.of(context).pop();
      }
    } on MatrixException catch (e) {
      if (mounted) setState(() { _creating = false; _createError = e.errorMessage; });
    } catch (e) {
      if (mounted) setState(() { _creating = false; _createError = e.toString().split('\n').first; });
    }
  }

  Future<void> _join() async {
    final addr = _joinCtrl.text.trim();
    if (addr.isEmpty) {
      setState(() => _joinError = 'Bitte eine Raum-Adresse eingeben.');
      return;
    }
    setState(() { _joining = true; _joinError = null; });
    try {
      final client = await ref.read(matrixClientProvider.future);
      final roomId = await client.joinRoom(addr);
      if (mounted) {
        ref.read(activeRoomIdProvider.notifier).state = roomId;
        ref.read(viewModeProvider.notifier).state = ViewMode.chat;
        Navigator.of(context).pop();
      }
    } on MatrixException catch (e) {
      if (mounted) setState(() { _joining = false; _joinError = e.errorMessage; });
    } catch (e) {
      if (mounted) setState(() { _joining = false; _joinError = e.toString().split('\n').first; });
    }
  }

  Future<void> _discover({bool loadMore = false}) async {
    if (loadMore) {
      if (_nextBatch == null) return;
      setState(() => _discoverLoadingMore = true);
    } else {
      setState(() { _discoverLoading = true; _discoverError = null; });
    }
    try {
      final client = await ref.read(matrixClientProvider.future);
      final server = _discoverServerCtrl.text.trim().isEmpty ? null : _discoverServerCtrl.text.trim();
      final search = _discoverSearchCtrl.text.trim();
      final res = await client.queryPublicRooms(
        server: server,
        limit: 30,
        since: loadMore ? _nextBatch : null,
        filter: search.isEmpty ? null : PublicRoomQueryFilter(genericSearchTerm: search),
      );
      if (mounted) {
        setState(() {
          if (loadMore) {
            _publicRooms.addAll(res.chunk);
          } else {
            _publicRooms = res.chunk;
          }
          _nextBatch = res.nextBatch;
          _discoverLoading = false;
          _discoverLoadingMore = false;
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _discoverLoading = false;
          _discoverLoadingMore = false;
          _discoverError = e.toString().split('\n').first;
        });
      }
    }
  }

  void _onSearchChanged(String _) {
    _searchDebounce?.cancel();
    _searchDebounce = Timer(const Duration(milliseconds: 500), _discover);
  }

  Future<void> _joinPublicRoom(String roomId, List<String>? via) async {
    setState(() => _joiningRooms.add(roomId));
    try {
      final client = await ref.read(matrixClientProvider.future);
      final id = await client.joinRoom(roomId, via: via);
      if (mounted) {
        ref.read(activeRoomIdProvider.notifier).state = id;
        ref.read(viewModeProvider.notifier).state = ViewMode.chat;
        Navigator.of(context).pop();
      }
    } catch (_) {
      if (mounted) setState(() => _joiningRooms.remove(roomId));
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = PyramidTheme.of(context);
    final size = MediaQuery.sizeOf(context);
    final isNarrow = size.width < 600;

    return Dialog(
      backgroundColor: pt.bg1,
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)),
      child: ConstrainedBox(
        constraints: BoxConstraints(
          maxWidth: isNarrow ? size.width * 0.97 : 580,
          maxHeight: size.height * 0.85,
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            _buildTabs(pt),
            Divider(color: pt.border, height: 1),
            Flexible(child: _buildBody(pt)),
          ],
        ),
      ),
    );
  }

  Widget _buildTabs(PyramidTheme pt) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(20, 16, 12, 12),
      child: Row(
        children: [
          Expanded(
            child: Row(
              children: [
                _Tab(label: 'Erstellen', icon: Icons.add_rounded, active: _tab == CreateJoinTab.create,
                    pt: pt, onTap: () => setState(() => _tab = CreateJoinTab.create)),
                const SizedBox(width: 4),
                _Tab(label: 'Beitreten', icon: Icons.login_rounded, active: _tab == CreateJoinTab.join,
                    pt: pt, onTap: () => setState(() => _tab = CreateJoinTab.join)),
                const SizedBox(width: 4),
                _Tab(label: 'Entdecken', icon: Icons.explore_rounded, active: _tab == CreateJoinTab.discover,
                    pt: pt, onTap: () {
                  setState(() => _tab = CreateJoinTab.discover);
                  if (_publicRooms.isEmpty) _discover();
                }),
              ],
            ),
          ),
          IconButton(
            icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16),
            onPressed: () => Navigator.of(context).pop(),
            padding: EdgeInsets.zero,
            constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28),
          ),
        ],
      ),
    );
  }

  Widget _buildBody(PyramidTheme pt) {
    return switch (_tab) {
      CreateJoinTab.create => _buildCreate(pt),
      CreateJoinTab.join => _buildJoin(pt),
      CreateJoinTab.discover => _buildDiscover(pt),
    };
  }

  Widget _buildCreate(PyramidTheme pt) {
    return SingleChildScrollView(
      padding: const EdgeInsets.fromLTRB(20, 4, 20, 20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Type toggle
          Row(children: [
            _TypeToggle(
              label: 'Raum',
              icon: Icons.tag_rounded,
              active: _createType == _CreateType.room,
              pt: pt,
              onTap: () => setState(() { _createType = _CreateType.room; _isPublic = false; }),
            ),
            const SizedBox(width: 8),
            _TypeToggle(
              label: 'Voice',
              icon: Icons.mic_rounded,
              active: _createType == _CreateType.voice,
              pt: pt,
              onTap: () => setState(() { _createType = _CreateType.voice; _isPublic = false; }),
            ),
            const SizedBox(width: 8),
            _TypeToggle(
              label: 'Space',
              icon: Icons.workspaces_rounded,
              active: _createType == _CreateType.space,
              pt: pt,
              onTap: () => setState(() => _createType = _CreateType.space),
            ),
          ]),
          const SizedBox(height: 16),
          _Field(ctrl: _nameCtrl, label: 'Name *', pt: pt, autofocus: true),
          const SizedBox(height: 10),
          _Field(ctrl: _topicCtrl, label: 'Thema / Beschreibung (optional)', pt: pt, maxLines: 2),
          const SizedBox(height: 14),
          // Options
          if (_createType == _CreateType.voice)
            Padding(
              padding: const EdgeInsets.only(bottom: 8),
              child: Row(
                children: [
                  Icon(Icons.info_outline, size: 14, color: pt.fgDim),
                  const SizedBox(width: 6),
                  Expanded(
                    child: Text(
                      'Voice-Kanäle sind privat. Mitglieder können beitreten und direkt sprechen.',
                      style: TextStyle(color: pt.fgDim, fontSize: 12),
                    ),
                  ),
                ],
              ),
            ),
          if (_createType != _CreateType.voice) ...[
            _OptionRow(
              label: 'Öffentlich',
              desc: 'Im Verzeichnis sichtbar, jeder kann beitreten',
              pt: pt,
              value: _isPublic,
              onChanged: (v) => setState(() => _isPublic = v),
            ),
            if (_createType == _CreateType.room) ...[
              const SizedBox(height: 8),
              _OptionRow(
                label: 'Verschlüsselt',
                desc: 'Ende-zu-Ende-Verschlüsselung aktivieren',
                pt: pt,
                value: _isEncrypted,
                onChanged: (v) => setState(() => _isEncrypted = v),
              ),
            ],
            if (_isPublic) ...[
              const SizedBox(height: 10),
              _Field(
                ctrl: _aliasCtrl,
                label: 'Alias (optional)',
                pt: pt,
                hint: 'mein-raum  →  #mein-raum:server',
              ),
            ],
          ],
          if (_createError != null) ...[
            const SizedBox(height: 10),
            _ErrorCard(text: _createError!, pt: pt),
          ],
          const SizedBox(height: 16),
          SizedBox(
            width: double.infinity,
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(
                backgroundColor: pt.accent, foregroundColor: pt.accentFg,
                elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12),
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
              ),
              onPressed: _creating ? null : _create,
              child: _creating
                  ? const SizedBox(width: 18, height: 18, child: CircularProgressIndicator.adaptive(strokeWidth: 2))
                  : Text(_createType == _CreateType.space ? 'Space erstellen' : 'Raum erstellen'),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildJoin(PyramidTheme pt) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(20, 8, 20, 20),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Raum-Adresse oder ID eingeben',
              style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5)),
          const SizedBox(height: 12),
          _Field(
            ctrl: _joinCtrl,
            label: 'Adresse oder ID',
            hint: '#kanal:server.de  oder  !abc123:server.de',
            pt: pt,
            autofocus: true,
            onSubmitted: (_) => _join(),
          ),
          const SizedBox(height: 6),
          Text('Tipp: Matrix-Räume, Spaces und Gruppen werden alle unterstützt.',
              style: TextStyle(color: pt.fgDim, fontSize: 11)),
          if (_joinError != null) ...[
            const SizedBox(height: 10),
            _ErrorCard(text: _joinError!, pt: pt),
          ],
          const SizedBox(height: 16),
          SizedBox(
            width: double.infinity,
            child: ElevatedButton(
              style: ElevatedButton.styleFrom(
                backgroundColor: pt.accent, foregroundColor: pt.accentFg,
                elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12),
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
              ),
              onPressed: _joining ? null : _join,
              child: _joining
                  ? const SizedBox(width: 18, height: 18, child: CircularProgressIndicator.adaptive(strokeWidth: 2))
                  : const Text('Beitreten'),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildDiscover(PyramidTheme pt) {
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
          child: Row(children: [
            Expanded(
              child: _Field(
                ctrl: _discoverSearchCtrl,
                label: 'Suchen',
                pt: pt,
                onChanged: _onSearchChanged,
                prefixIcon: Icon(Icons.search_rounded, size: 16, color: pt.fgDim),
              ),
            ),
            const SizedBox(width: 8),
            SizedBox(
              width: 140,
              child: _Field(
                ctrl: _discoverServerCtrl,
                label: 'Server',
                hint: 'matrix.org',
                pt: pt,
                onSubmitted: (_) => _discover(),
              ),
            ),
          ]),
        ),
        Divider(color: pt.border, height: 1),
        Flexible(
          child: _discoverLoading
              ? const Center(child: CircularProgressIndicator.adaptive())
              : _discoverError != null
                  ? Center(child: _ErrorCard(text: _discoverError!, pt: pt))
                  : _publicRooms.isEmpty
                      ? Center(child: Text('Keine Räume gefunden.', style: TextStyle(color: pt.fgMuted, fontSize: 13)))
                      : ListView.builder(
                          itemCount: _publicRooms.length + (_nextBatch != null ? 1 : 0),
                          itemBuilder: (ctx, i) {
                            if (i == _publicRooms.length) {
                              return Padding(
                                padding: const EdgeInsets.all(12),
                                child: Center(
                                  child: _discoverLoadingMore
                                      ? const CircularProgressIndicator.adaptive()
                                      : TextButton(
                                          onPressed: () => _discover(loadMore: true),
                                          child: Text('Mehr laden', style: TextStyle(color: pt.accent)),
                                        ),
                                ),
                              );
                            }
                            final room = _publicRooms[i];
                            return _PublicRoomItem(
                              room: room,
                              pt: pt,
                              isJoining: _joiningRooms.contains(room.roomId),
                              onJoin: () => _joinPublicRoom(room.roomId, null),
                            );
                          },
                        ),
        ),
      ],
    );
  }
}

// ── Space / Room editor dialog ─────────────────────────────────────────────────

class SpaceEditDialog extends ConsumerStatefulWidget {
  final Room space;
  const SpaceEditDialog({super.key, required this.space});

  @override
  ConsumerState<SpaceEditDialog> createState() => _SpaceEditDialogState();
}

class _SpaceEditDialogState extends ConsumerState<SpaceEditDialog> {
  late TextEditingController _nameCtrl;
  late TextEditingController _topicCtrl;
  bool _saving = false;
  String? _error;

  @override
  void initState() {
    super.initState();
    _nameCtrl = TextEditingController(text: widget.space.getLocalizedDisplayname());
    _topicCtrl = TextEditingController(text: widget.space.topic);
  }

  @override
  void dispose() {
    _nameCtrl.dispose();
    _topicCtrl.dispose();
    super.dispose();
  }

  Future<void> _save() async {
    setState(() { _saving = true; _error = null; });
    try {
      final name = _nameCtrl.text.trim();
      final topic = _topicCtrl.text.trim();
      if (name.isNotEmpty && name != widget.space.getLocalizedDisplayname()) {
        await widget.space.setName(name);
      }
      if (topic != widget.space.topic) {
        await widget.space.setDescription(topic);
      }
      if (mounted) setState(() { _saving = false; });
      await Future.delayed(const Duration(seconds: 1));
      if (mounted) Navigator.of(context).pop(true);
    } catch (e) {
      if (mounted) setState(() { _saving = false; _error = e.toString().split('\n').first; });
    }
  }

  Future<void> _leave() async {
    final pt = PyramidTheme.of(context);
    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('Space verlassen?',
            style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)),
        content: Text('Du verlässt "${widget.space.getLocalizedDisplayname()}".',
            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 {
      await widget.space.leave();
      if (mounted) {
        ref.read(activeSpaceIdProvider.notifier).state = 'rooms';
        Navigator.of(context).pop(true);
      }
    } catch (e) {
      if (mounted) setState(() => _error = e.toString().split('\n').first);
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = PyramidTheme.of(context);
    return Dialog(
      backgroundColor: pt.bg2,
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)),
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 420),
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(children: [
                Icon(Icons.workspaces_rounded, size: 18, color: pt.accent),
                const SizedBox(width: 8),
                Expanded(child: Text('Space bearbeiten',
                    style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600))),
                IconButton(
                  icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16),
                  onPressed: () => Navigator.of(context).pop(),
                  padding: EdgeInsets.zero,
                  constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28),
                ),
              ]),
              const SizedBox(height: 16),
              _Field(ctrl: _nameCtrl, label: 'Name', pt: pt),
              const SizedBox(height: 10),
              _Field(ctrl: _topicCtrl, label: 'Beschreibung', pt: pt, maxLines: 2),
              if (_error != null) ...[
                const SizedBox(height: 10),
                _ErrorCard(text: _error!, pt: pt),
              ],
              const SizedBox(height: 16),
              Row(children: [
                Expanded(child: OutlinedButton(
                  style: OutlinedButton.styleFrom(
                      foregroundColor: pt.danger, side: BorderSide(color: pt.danger.withAlpha(80)),
                      padding: const EdgeInsets.symmetric(vertical: 10),
                      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
                  onPressed: _leave,
                  child: const Text('Verlassen'),
                )),
                const SizedBox(width: 10),
                Expanded(child: ElevatedButton(
                  style: ElevatedButton.styleFrom(
                      backgroundColor: pt.accent, foregroundColor: pt.accentFg,
                      elevation: 0, padding: const EdgeInsets.symmetric(vertical: 10),
                      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
                  onPressed: _saving ? null : _save,
                  child: _saving
                      ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator.adaptive(strokeWidth: 2))
                      : const Text('Speichern'),
                )),
              ]),
            ],
          ),
        ),
      ),
    );
  }
}

// ── Room settings dialog ───────────────────────────────────────────────────────

class RoomSettingsDialog extends ConsumerStatefulWidget {
  final Room room;
  const RoomSettingsDialog({super.key, required this.room});

  @override
  ConsumerState<RoomSettingsDialog> createState() => _RoomSettingsDialogState();
}

class _RoomSettingsDialogState extends ConsumerState<RoomSettingsDialog> {
  late TextEditingController _nameCtrl;
  late TextEditingController _topicCtrl;
  bool _saving = false;
  String? _error;

  @override
  void initState() {
    super.initState();
    _nameCtrl = TextEditingController(text: widget.room.getLocalizedDisplayname());
    _topicCtrl = TextEditingController(text: widget.room.topic);
  }

  @override
  void dispose() {
    _nameCtrl.dispose();
    _topicCtrl.dispose();
    super.dispose();
  }

  Future<void> _save() async {
    setState(() { _saving = true; _error = null; });
    try {
      if (_nameCtrl.text.trim() != widget.room.getLocalizedDisplayname()) {
        await widget.room.setName(_nameCtrl.text.trim());
      }
      final newTopic = _topicCtrl.text.trim();
      if (newTopic != widget.room.topic) {
        await widget.room.setDescription(newTopic);
      }
      if (mounted) Navigator.of(context).pop();
    } catch (e) {
      if (mounted) setState(() { _saving = false; _error = e.toString().split('\n').first; });
    }
  }

  Future<void> _leaveRoom() async {
    final pt = PyramidTheme.of(context);
    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 roomId = widget.room.id;
      await widget.room.leave();
      if (mounted) {
        final current = ref.read(activeRoomIdProvider);
        if (current == roomId) ref.read(activeRoomIdProvider.notifier).state = null;
        Navigator.of(context).pop();
      }
    } catch (e) {
      if (mounted) setState(() => _error = e.toString().split('\n').first);
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = PyramidTheme.of(context);
    final canEdit = widget.room.canSendEvent(EventTypes.RoomName);

    return Dialog(
      backgroundColor: pt.bg2,
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)),
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 400),
        child: Padding(
          padding: const EdgeInsets.all(24),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(children: [
                Icon(Icons.settings_rounded, size: 18, color: pt.accent),
                const SizedBox(width: 8),
                Expanded(child: Text('Raum-Einstellungen',
                    style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600))),
                IconButton(
                  icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16),
                  onPressed: () => Navigator.of(context).pop(),
                  padding: EdgeInsets.zero,
                  constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28),
                ),
              ]),
              const SizedBox(height: 6),
              SelectableText(widget.room.id,
                  style: TextStyle(color: pt.fgDim, fontSize: 11, fontFamily: 'monospace')),
              const SizedBox(height: 16),
              if (canEdit) ...[
                _Field(ctrl: _nameCtrl, label: 'Name', pt: pt),
                const SizedBox(height: 10),
                _Field(ctrl: _topicCtrl, label: 'Thema', pt: pt, maxLines: 2),
              ] else
                Text('Du hast keine Berechtigung, diesen Raum zu bearbeiten.',
                    style: TextStyle(color: pt.fgMuted, fontSize: 13)),
              if (_error != null) ...[
                const SizedBox(height: 10),
                _ErrorCard(text: _error!, pt: pt),
              ],
              const SizedBox(height: 16),
              Row(children: [
                Expanded(child: OutlinedButton(
                  style: OutlinedButton.styleFrom(
                      foregroundColor: pt.danger, side: BorderSide(color: pt.danger.withAlpha(80)),
                      padding: const EdgeInsets.symmetric(vertical: 10),
                      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
                  onPressed: _leaveRoom,
                  child: const Text('Verlassen'),
                )),
                if (canEdit) ...[
                  const SizedBox(width: 10),
                  Expanded(child: ElevatedButton(
                    style: ElevatedButton.styleFrom(
                        backgroundColor: pt.accent, foregroundColor: pt.accentFg,
                        elevation: 0, padding: const EdgeInsets.symmetric(vertical: 10),
                        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
                    onPressed: _saving ? null : _save,
                    child: _saving
                        ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator.adaptive(strokeWidth: 2))
                        : const Text('Speichern'),
                  )),
                ],
              ]),
            ],
          ),
        ),
      ),
    );
  }
}

// ── Helper widgets ─────────────────────────────────────────────────────────────

class _Tab extends StatefulWidget {
  final String label;
  final IconData icon;
  final bool active;
  final PyramidTheme pt;
  final VoidCallback onTap;
  const _Tab({required this.label, required this.icon, required this.active, required this.pt, required this.onTap});

  @override
  State<_Tab> createState() => _TabState();
}

class _TabState extends State<_Tab> {
  bool _hovered = false;

  @override
  Widget build(BuildContext context) {
    final pt = widget.pt;
    return MouseRegion(
      cursor: SystemMouseCursors.click,
      onEnter: (_) => setState(() => _hovered = true),
      onExit: (_) => setState(() => _hovered = false),
      child: GestureDetector(
        onTap: widget.onTap,
        child: AnimatedContainer(
          duration: const Duration(milliseconds: 150),
          padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
          decoration: BoxDecoration(
            color: widget.active ? pt.accentSoft : (_hovered ? pt.bgHover : Colors.transparent),
            borderRadius: BorderRadius.circular(6),
          ),
          child: Row(mainAxisSize: MainAxisSize.min, children: [
            Icon(widget.icon, size: 14, color: widget.active ? pt.accent : pt.fgMuted),
            const SizedBox(width: 6),
            Text(widget.label, style: TextStyle(
              color: widget.active ? pt.fg : pt.fgMuted,
              fontSize: 13, fontWeight: widget.active ? FontWeight.w600 : FontWeight.w400,
            )),
          ]),
        ),
      ),
    );
  }
}

class _TypeToggle extends StatelessWidget {
  final String label;
  final IconData icon;
  final bool active;
  final PyramidTheme pt;
  final VoidCallback onTap;
  const _TypeToggle({required this.label, required this.icon, required this.active, required this.pt, required this.onTap});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 150),
        padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
        decoration: BoxDecoration(
          color: active ? pt.accent : pt.bg3,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: active ? pt.accent : pt.border),
        ),
        child: Row(mainAxisSize: MainAxisSize.min, children: [
          Icon(icon, size: 14, color: active ? pt.accentFg : pt.fgMuted),
          const SizedBox(width: 6),
          Text(label, style: TextStyle(
            color: active ? pt.accentFg : pt.fgMuted,
            fontSize: 13, fontWeight: FontWeight.w500,
          )),
        ]),
      ),
    );
  }
}

class _OptionRow extends StatelessWidget {
  final String label;
  final String desc;
  final bool value;
  final ValueChanged<bool> onChanged;
  final PyramidTheme pt;
  const _OptionRow({required this.label, required this.desc, required this.value, required this.onChanged, required this.pt});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => onChanged(!value),
      child: Row(children: [
        Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Text(label, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500)),
          Text(desc, style: TextStyle(color: pt.fgDim, fontSize: 11)),
        ])),
        Switch(value: value, onChanged: onChanged, activeThumbColor: pt.accent),
      ]),
    );
  }
}

class _Field extends StatelessWidget {
  final TextEditingController ctrl;
  final String label;
  final String? hint;
  final PyramidTheme pt;
  final bool autofocus;
  final int maxLines;
  final Widget? prefixIcon;
  final ValueChanged<String>? onChanged;
  final ValueChanged<String>? onSubmitted;

  const _Field({
    required this.ctrl, required this.label, required this.pt,
    this.hint, this.autofocus = false, this.maxLines = 1,
    this.prefixIcon, this.onChanged, this.onSubmitted,
  });

  @override
  Widget build(BuildContext context) => TextField(
    controller: ctrl,
    autofocus: autofocus,
    maxLines: maxLines,
    style: TextStyle(color: pt.fg, fontSize: 13),
    onChanged: onChanged,
    onSubmitted: onSubmitted,
    decoration: InputDecoration(
      labelText: label,
      hintText: hint,
      labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13),
      hintStyle: TextStyle(color: pt.fgDim, fontSize: 12),
      prefixIcon: prefixIcon,
      filled: true, fillColor: pt.bg3,
      isDense: true,
      contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
      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,
  );
}

class _ErrorCard extends StatelessWidget {
  final String text;
  final PyramidTheme pt;
  const _ErrorCard({required this.text, required this.pt});

  @override
  Widget build(BuildContext context) => Container(
    padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
    decoration: BoxDecoration(
      color: pt.danger.withAlpha(20),
      borderRadius: BorderRadius.circular(8),
      border: Border.all(color: pt.danger.withAlpha(60)),
    ),
    child: Row(children: [
      Icon(Icons.error_outline_rounded, size: 14, color: pt.danger),
      const SizedBox(width: 8),
      Expanded(child: Text(text, style: TextStyle(color: pt.danger, fontSize: 12))),
    ]),
  );
}

class _PublicRoomItem extends ConsumerWidget {
  final PublishedRoomsChunk room;
  final PyramidTheme pt;
  final bool isJoining;
  final VoidCallback onJoin;
  const _PublicRoomItem({required this.room, required this.pt, required this.isJoining, required this.onJoin});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final client = ref.watch(matrixClientProvider).valueOrNull;
    final name = room.name ?? room.canonicalAlias ?? room.roomId;
    final avatarUrl = room.avatarUrl;
    final alreadyJoined = client?.getRoomById(room.roomId) != null;

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
      child: Row(children: [
        // Avatar
        Container(
          width: 36, height: 36,
          decoration: BoxDecoration(color: pt.bg3, borderRadius: BorderRadius.circular(8)),
          child: (client != null && avatarUrl != null)
              ? ClipRRect(
                  borderRadius: BorderRadius.circular(8),
                  child: MxcImage(mxcUri: avatarUrl.toString(), client: client, fit: BoxFit.cover),
                )
              : Center(child: Text(
                  name.isNotEmpty ? name[0].toUpperCase() : '?',
                  style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w700),
                )),
        ),
        const SizedBox(width: 10),
        Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Text(name, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500),
              overflow: TextOverflow.ellipsis),
          if (room.topic != null)
            Text(room.topic!, style: TextStyle(color: pt.fgDim, fontSize: 11),
                overflow: TextOverflow.ellipsis, maxLines: 1),
          Text('${room.numJoinedMembers} Mitglieder',
              style: TextStyle(color: pt.fgDim, fontSize: 11)),
        ])),
        const SizedBox(width: 8),
        if (alreadyJoined)
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
            decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(6)),
            child: Text('Beigetreten', style: TextStyle(color: pt.accent, fontSize: 11, fontWeight: FontWeight.w600)),
          )
        else if (isJoining)
          const SizedBox(width: 20, height: 20, child: CircularProgressIndicator.adaptive(strokeWidth: 2))
        else
          ElevatedButton(
            style: ElevatedButton.styleFrom(
              backgroundColor: pt.accent, foregroundColor: pt.accentFg,
              elevation: 0, padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
              minimumSize: Size.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap,
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
            ),
            onPressed: onJoin,
            child: const Text('Beitreten', style: TextStyle(fontSize: 12)),
          ),
      ]),
    );
  }
}
