part of '../space_admin_dialog.dart';

class _OverviewTab extends ConsumerStatefulWidget {
  final Room space;
  const _OverviewTab({required this.space});

  @override
  ConsumerState<_OverviewTab> createState() => _OverviewTabState();
}

class _OverviewTabState extends ConsumerState<_OverviewTab> {
  late TextEditingController _nameCtrl;
  late TextEditingController _topicCtrl;
  bool _saving = false;
  String? _error;
  String? _success;
  Uint8List? _pendingBanner;
  String? _bannerMxcUri;
  Uint8List? _pendingAvatar;

  @override
  void initState() {
    super.initState();
    _nameCtrl = TextEditingController(
        text: widget.space.getLocalizedDisplayname());
    _topicCtrl = TextEditingController(text: widget.space.topic);
    // Prefer local override (set on last save) over room state event
    final overrides = ref.read(spaceBannerOverrideProvider);
    _bannerMxcUri = overrides.containsKey(widget.space.id)
        ? overrides[widget.space.id]
        : widget.space.getState(_kSpaceBannerEvent)?.content['url'] as String?;
  }

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

  Future<void> _pickBanner() async {
    final result = await FilePicker.platform
        .pickFiles(type: FileType.image, withData: true);
    final file = result?.files.first;
    if (file == null) return;
    final raw = file.bytes ?? await file.xFile.readAsBytes();
    if (!mounted) return;
    final cropped = await showDialog<Uint8List>(
      context: context,
      builder: (_) => BannerCropDialog(imageBytes: raw, aspectRatio: 2.4),
    );
    if (cropped == null || !mounted) return;
    setState(() => _pendingBanner = cropped);
  }

  Future<void> _pickAvatar() async {
    final result = await FilePicker.platform
        .pickFiles(type: FileType.image, withData: true);
    final file = result?.files.first;
    if (file == null) return;
    final raw = file.bytes ?? await file.xFile.readAsBytes();
    if (!mounted) return;
    setState(() => _pendingAvatar = raw);
  }

  Future<void> _removeAvatar() async {
    setState(() => _pendingAvatar = null);
    try {
      await widget.space.client.setRoomStateWithKey(
          widget.space.id, EventTypes.RoomAvatar, '', {});
    } catch (_) {}
  }

  Future<void> _removeBanner() async {
    setState(() { _pendingBanner = null; _bannerMxcUri = null; });
    try {
      await widget.space.client.setRoomStateWithKey(
          widget.space.id, _kSpaceBannerEvent, '', {});
    } catch (_) {}
  }

  Future<void> _save() async {
    setState(() { _saving = true; _error = null; _success = null; });
    // Welcher Schritt gerade läuft — für präzise Fehlermeldungen statt eines
    // pauschalen "keine Berechtigung" (das auch von Upload-Fehlern kam).
    var step = 'Speichern';
    try {
      final client = widget.space.client;
      final newName = _nameCtrl.text.trim();
      final newTopic = _topicCtrl.text.trim();
      if (newName.isNotEmpty &&
          newName != widget.space.getLocalizedDisplayname()) {
        step = 'Name ändern';
        await widget.space.setName(newName);
      }
      if (newTopic != widget.space.topic) {
        step = 'Beschreibung ändern';
        await widget.space.setDescription(newTopic);
      }
      if (_pendingAvatar != null) {
        step = 'Avatar hochladen';
        final uri = await client.uploadContent(
          _pendingAvatar!,
          filename: 'space_avatar.jpg',
          contentType: 'image/jpeg',
        );
        step = 'Avatar setzen';
        await _setStateWithRepair(
          client,
          EventTypes.RoomAvatar,
          {'url': uri.toString()},
        );
        setState(() => _pendingAvatar = null);
      }
      if (_pendingBanner != null) {
        step = 'Banner hochladen';
        final uri = await client.uploadContent(
          _pendingBanner!,
          filename: 'space_banner.jpg',
          contentType: 'image/jpeg',
        );
        step = 'Banner setzen';
        await _setStateWithRepair(
          client,
          _kSpaceBannerEvent,
          {'url': uri.toString()},
        );
        final uriStr = uri.toString();
        // Update local override immediately so header updates before next sync
        ref.read(spaceBannerOverrideProvider.notifier).update(
              (m) => {...m, widget.space.id: uriStr},
            );
        setState(() {
          _bannerMxcUri = uriStr;
          _pendingBanner = null;
        });
      }
      setState(() { _success = 'Gespeichert'; });
    } catch (e) {
      // Server-Fehlertext anzeigen (MatrixException liefert lesbare Meldung) —
      // nicht pauschal auf "Admin-Level erforderlich" mappen.
      final raw = e is MatrixException
          ? '${e.errcode}: ${e.errorMessage}'
          : e.toString().split('\n').first;
      var detail = '';
      if (e is MatrixException && e.errcode == 'M_FORBIDDEN') {
        detail = '\n${_permDiagnostics()}';
        // Zusätzlich die SERVER-Sicht der Power-Levels holen — die lokale
        // Kopie kann von der des Servers abweichen.
        try {
          final pl = await widget.space.client.getRoomStateWithKey(
              widget.space.id, EventTypes.RoomPowerLevels, '');
          detail +=
              '\nServer-PL: users=${pl['users']}, state_default=${pl['state_default']}, events=${pl['events']}';
        } on MatrixException catch (se) {
          detail += '\nServer-PL: ${se.errcode} (Event fehlt auch serverseitig)';
        } catch (_) {}
      }
      setState(() {
        _error = '$step fehlgeschlagen – $raw$detail';
      });
    } finally {
      setState(() { _saving = false; });
    }
  }

  /// Sendet ein State-Event; bei M_FORBIDDEN in einem Raum OHNE
  /// power_levels-Event (Continuwuity-Sonderfall: Server verweigert dann
  /// Custom-State trotz Creator-Rechten) werden einmalig Standard-Power-Levels
  /// mit uns als Admin angelegt und der Vorgang wiederholt.
  Future<void> _setStateWithRepair(
    Client client,
    String type,
    Map<String, Object?> content,
  ) async {
    try {
      await client.setRoomStateWithKey(widget.space.id, type, '', content);
    } on MatrixException catch (e) {
      if (e.errcode != 'M_FORBIDDEN') rethrow;
      final repaired = await _ensurePowerLevels(client);
      if (!repaired) rethrow;
      await client.setRoomStateWithKey(widget.space.id, type, '', content);
    }
  }

  /// Legt Standard-Power-Levels an, falls der Raum keine hat.
  /// Gibt true zurück, wenn das Event neu angelegt wurde.
  Future<bool> _ensurePowerLevels(Client client) async {
    try {
      await client.getRoomStateWithKey(
          widget.space.id, EventTypes.RoomPowerLevels, '');
      return false; // existiert bereits — Ablehnung hat andere Ursache
    } catch (_) {
      // fehlt (M_NOT_FOUND) → anlegen
    }
    try {
      await client.setRoomStateWithKey(
        widget.space.id,
        EventTypes.RoomPowerLevels,
        '',
        {
          'users': {client.userID!: 100},
          'users_default': 0,
          'events': const <String, Object?>{},
          'events_default': 0,
          'state_default': 50,
          'ban': 50,
          'kick': 50,
          'redact': 50,
          'invite': 0,
          'notifications': {'room': 50},
        },
      );
      return true;
    } catch (_) {
      return false;
    }
  }

  /// Kompakte Berechtigungs-Diagnose für M_FORBIDDEN-Fehler: zeigt, wie der
  /// Server die Lage vermutlich sieht (Raumversion, Creator, Power-Level).
  String _permDiagnostics() {
    try {
      final space = widget.space;
      final create = space.getState(EventTypes.RoomCreate);
      final version = create?.content['room_version'] ?? '1';
      final creator = create?.senderId ?? '?';
      final own = space.ownPowerLevel;
      final needed = space.powerForChangingStateEvent(_kSpaceBannerEvent);
      final hasPl = space.getState(EventTypes.RoomPowerLevels) != null;
      return 'Diagnose: dein Level $own, benötigt $needed, '
          'Raumversion $version, Creator $creator'
          '${hasPl ? '' : ', kein power_levels-Event vorhanden!'}';
    } catch (_) {
      return '';
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = PyramidTheme.of(context);
    final client = ref.watch(matrixClientProvider).valueOrNull;
    // SDK-Berechtigungsprüfung (berücksichtigt events-Overrides und
    // state_default) statt hartcodiertem Admin-Level 100.
    final canEdit = widget.space.canChangeStateEvent(EventTypes.RoomName) ||
        widget.space.ownPowerLevel >= _kPowerAdmin;
    return SingleChildScrollView(
      padding: const EdgeInsets.all(20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // ── Banner ────────────────────────────────────────────────────────
          _SectionLabel('Banner', pt),
          const SizedBox(height: 6),
          GestureDetector(
            onTap: canEdit ? _pickBanner : null,
            child: Stack(
              children: [
                AspectRatio(
                  aspectRatio: 2.4,
                  child: Container(
                  width: double.infinity,
                  decoration: BoxDecoration(
                    color: pt.bg0,
                    borderRadius: BorderRadius.circular(pt.rBase),
                    border: Border.all(color: pt.border),
                  ),
                  clipBehavior: Clip.hardEdge,
                  child: _pendingBanner != null
                      ? Image.memory(_pendingBanner!,
                          fit: BoxFit.cover, width: double.infinity)
                      : (_bannerMxcUri != null && client != null
                          ? MxcImage(
                              mxcUri: _bannerMxcUri!,
                              client: client,
                              fit: BoxFit.cover,
                              width: double.infinity,
                              placeholder: Container(color: pt.bg0),
                            )
                          : Center(
                              child: Column(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Icon(Icons.add_photo_alternate_outlined,
                                      size: 24, color: pt.fgDim),
                                  const SizedBox(height: 4),
                                  Text('Banner hinzufügen',
                                      style: TextStyle(
                                          color: pt.fgDim, fontSize: 12)),
                                ],
                              ),
                            )),
                  ), // Container
                ), // AspectRatio
                if (canEdit)
                  Positioned(
                    right: 6,
                    bottom: 6,
                    child: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        if (_bannerMxcUri != null || _pendingBanner != null)
                          GestureDetector(
                            onTap: _removeBanner,
                            child: Container(
                              margin: const EdgeInsets.only(right: 4),
                              padding: const EdgeInsets.symmetric(
                                  horizontal: 7, vertical: 3),
                              decoration: BoxDecoration(
                                color: const Color(0xFFED4245).withAlpha(200),
                                borderRadius: BorderRadius.circular(5),
                              ),
                              child: const Row(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Icon(Icons.delete_outline,
                                      size: 11, color: Colors.white),
                                  SizedBox(width: 3),
                                  Text('Entfernen',
                                      style: TextStyle(
                                          color: Colors.white, fontSize: 11)),
                                ],
                              ),
                            ),
                          ),
                        Container(
                          padding: const EdgeInsets.symmetric(
                              horizontal: 7, vertical: 3),
                          decoration: BoxDecoration(
                            color: pt.bg0.withAlpha(200),
                            borderRadius: BorderRadius.circular(5),
                            border: Border.all(color: pt.border),
                          ),
                          child: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Icon(Icons.edit_rounded,
                                  size: 11, color: pt.fgMuted),
                              const SizedBox(width: 3),
                              Text('Banner ändern',
                                  style: TextStyle(
                                      color: pt.fgMuted, fontSize: 11)),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
              ],
            ),
          ),
          const SizedBox(height: 16),
          // ── Avatar ───────────────────────────────────────────────────────
          _SectionLabel('Serverbild', pt),
          const SizedBox(height: 8),
          _AvatarEditor(
            space: widget.space,
            pendingAvatar: _pendingAvatar,
            canEdit: canEdit,
            onPick: _pickAvatar,
            onRemove: _removeAvatar,
            pt: pt,
            client: client,
          ),
          const SizedBox(height: 16),
          // ── Name / Topic ─────────────────────────────────────────────────
          _SectionLabel('Name', pt),
          const SizedBox(height: 6),
          _Field(controller: _nameCtrl, hint: 'Space-Name', pt: pt),
          const SizedBox(height: 16),
          _SectionLabel('Beschreibung', pt),
          const SizedBox(height: 6),
          _Field(
              controller: _topicCtrl,
              hint: 'Worum geht es in diesem Space?',
              maxLines: 4,
              pt: pt),
          const SizedBox(height: 8),
          _SpaceVisibilityToggle(space: widget.space),
          const SizedBox(height: 20),
          if (_error != null)
            Padding(
              padding: const EdgeInsets.only(bottom: 8),
              child: Text(_error!,
                  style: const TextStyle(color: Color(0xFFED4245), fontSize: 12)),
            ),
          if (_success != null)
            Padding(
              padding: const EdgeInsets.only(bottom: 8),
              child: Text(_success!,
                  style: const TextStyle(color: Color(0xFF57F287), fontSize: 12)),
            ),
          SizedBox(
            width: double.infinity,
            child: FilledButton(
              onPressed: _saving ? null : _save,
              style: FilledButton.styleFrom(
                backgroundColor: pt.accent,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(pt.rBase)),
              ),
              child: _saving
                  ? SizedBox(
                      width: 18,
                      height: 18,
                      child: CircularProgressIndicator(
                          strokeWidth: 2, color: pt.bg0))
                  : const Text('Speichern',
                      style: TextStyle(
                          color: Colors.white, fontWeight: FontWeight.w600)),
            ),
          ),
          const SizedBox(height: 24),
          _DangerZone(space: widget.space),
        ],
      ),
    );
  }
}

class _SpaceVisibilityToggle extends ConsumerStatefulWidget {
  final Room space;
  const _SpaceVisibilityToggle({required this.space});

  @override
  ConsumerState<_SpaceVisibilityToggle> createState() =>
      _SpaceVisibilityToggleState();
}

class _SpaceVisibilityToggleState
    extends ConsumerState<_SpaceVisibilityToggle> {
  bool? _isPublic;
  bool _loading = true;

  @override
  void initState() {
    super.initState();
    _load();
  }

  Future<void> _load() async {
    try {
      final joinRules = widget.space.joinRules;
      setState(() {
        _isPublic = joinRules == JoinRules.public;
        _loading = false;
      });
    } catch (_) {
      setState(() => _loading = false);
    }
  }

  Future<void> _toggle(bool value) async {
    setState(() => _isPublic = value);
    try {
      await widget.space.setJoinRules(
          value ? JoinRules.public : JoinRules.invite);
    } catch (_) {
      setState(() => _isPublic = !value);
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = PyramidTheme.of(context);
    if (_loading) return const SizedBox.shrink();
    return Row(
      children: [
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('Öffentlicher Space',
                  style: TextStyle(
                      color: pt.fg,
                      fontSize: 13,
                      fontWeight: FontWeight.w600)),
              Text('Jeder kann diesem Space beitreten',
                  style: TextStyle(color: pt.fgDim, fontSize: 12)),
            ],
          ),
        ),
        Switch(
          value: _isPublic ?? false,
          onChanged: _toggle,
          activeThumbColor: pt.accent,
        ),
      ],
    );
  }
}

class _DangerZone extends ConsumerWidget {
  final Room space;
  const _DangerZone({required this.space});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final pt = PyramidTheme.of(context);
    return Container(
      decoration: BoxDecoration(
        border: Border.all(color: const Color(0xFFED4245).withAlpha(80)),
        borderRadius: BorderRadius.circular(pt.rBase),
      ),
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Gefahrenzone',
              style: TextStyle(
                  color: const Color(0xFFED4245),
                  fontSize: 13,
                  fontWeight: FontWeight.w700)),
          const SizedBox(height: 12),
          Row(
            children: [
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text('Space verlassen',
                        style: TextStyle(
                            color: pt.fg,
                            fontSize: 13,
                            fontWeight: FontWeight.w600)),
                    Text('Du verlässt diesen Space',
                        style: TextStyle(color: pt.fgDim, fontSize: 12)),
                  ],
                ),
              ),
              OutlinedButton(
                onPressed: () => _confirmLeave(context, ref),
                style: OutlinedButton.styleFrom(
                  foregroundColor: const Color(0xFFED4245),
                  side: const BorderSide(color: Color(0xFFED4245)),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8)),
                ),
                child: const Text('Verlassen'),
              ),
            ],
          ),
        ],
      ),
    );
  }

  void _confirmLeave(BuildContext context, WidgetRef ref) {
    showDialog(
      context: context,
      builder: (_) => AlertDialog(
        title: const Text('Space verlassen?'),
        content: Text(
            'Möchtest du "${space.getLocalizedDisplayname()}" wirklich verlassen?'),
        actions: [
          TextButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('Abbrechen')),
          TextButton(
            onPressed: () async {
              Navigator.pop(context);
              Navigator.pop(context);
              await space.leave();
            },
            child: const Text('Verlassen',
                style: TextStyle(color: Color(0xFFED4245))),
          ),
        ],
      ),
    );
  }
}
