part of '../../settings_modal.dart';

class _ChangeRecoveryKeyDialog extends ConsumerStatefulWidget {
  final PyramidTheme pt;
  const _ChangeRecoveryKeyDialog({required this.pt});

  @override
  ConsumerState<_ChangeRecoveryKeyDialog> createState() =>
      _ChangeRecoveryKeyDialogState();
}

class _ChangeRecoveryKeyDialogState
    extends ConsumerState<_ChangeRecoveryKeyDialog> {
  _RecoveryStep _step = _RecoveryStep.loading;
  String? _generatedKey;
  String? _error;
  bool _copied = false;
  // Completer signals when bootstrap reaches `done`
  final _doneCompleter = Completer<void>();

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

  Future<void> _startBootstrap() async {
    try {
      final client = await ref.read(matrixClientProvider.future);
      final enc = client.encryption;
      if (enc == null) throw Exception('Verschlüsselung nicht verfügbar.');
      await client.roomsLoading;
      await client.accountDataLoading;
      await client.userDeviceKeysLoading;
      enc.bootstrap(onUpdate: (bs) {
        if (!mounted) return;
        _onBootstrapUpdate(bs);
      });
    } catch (e) {
      if (mounted) {
        setState(() {
          _step = _RecoveryStep.error;
          _error = e.toString().split('\n').first;
        });
      }
    }
  }

  // After newSsss() calls checkCrossSigning(), the bootstrap immediately
  // transitions to askWipeCrossSigning (or askSetupCrossSigning). All post-
  // newSsss states must therefore auto-advance unconditionally — guarding on
  // _step would leave them stuck.
  void _onBootstrapUpdate(Bootstrap bs) {
    switch (bs.state) {
      case BootstrapState.askWipeSsss:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askWipeSsss) bs.wipeSsss(true);
        });
      case BootstrapState.askBadSsss:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askBadSsss) bs.ignoreBadSecrets(true);
        });
      case BootstrapState.askUseExistingSsss:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askUseExistingSsss) bs.useExistingSsss(false);
        });
      case BootstrapState.askUnlockSsss:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askUnlockSsss) bs.unlockedSsss();
        });
      case BootstrapState.askNewSsss:
        // Only generate once
        if (_step == _RecoveryStep.loading) {
          WidgetsBinding.instance.addPostFrameCallback((_) async {
            if (bs.state != BootstrapState.askNewSsss) return;
            try {
              await bs.newSsss();
              // newSsss() internally calls checkCrossSigning() which already
              // transitions to askWipeCrossSigning; capture key after it returns.
              final key = bs.newSsssKey?.recoveryKey;
              if (mounted) setState(() { _generatedKey = key; _step = _RecoveryStep.showKey; });
            } catch (e) {
              if (mounted) setState(() { _step = _RecoveryStep.error; _error = e.toString().split('\n').first; });
            }
          });
        }
      case BootstrapState.askWipeCrossSigning:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askWipeCrossSigning) bs.wipeCrossSigning(false);
        });
      case BootstrapState.askSetupCrossSigning:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askSetupCrossSigning) {
            bs.askSetupCrossSigning(
              setupMasterKey: true,
              setupSelfSigningKey: true,
              setupUserSigningKey: true,
            );
          }
        });
      case BootstrapState.askWipeOnlineKeyBackup:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askWipeOnlineKeyBackup) bs.wipeOnlineKeyBackup(true);
        });
      case BootstrapState.askSetupOnlineKeyBackup:
        WidgetsBinding.instance.addPostFrameCallback((_) {
          if (bs.state == BootstrapState.askSetupOnlineKeyBackup) bs.askSetupOnlineKeyBackup(true);
        });
      case BootstrapState.done:
        if (!_doneCompleter.isCompleted) _doneCompleter.complete();
        // Only auto-advance to done if user already clicked through (applying).
        // If still on showKey/confirmKey, the user must finish reading first.
        if (mounted && _step == _RecoveryStep.applying) {
          setState(() => _step = _RecoveryStep.done);
        }
      case BootstrapState.error:
        if (!_doneCompleter.isCompleted) _doneCompleter.completeError('Bootstrap-Fehler');
        if (mounted) setState(() { _step = _RecoveryStep.error; _error = 'Fehler bei der Schlüsselgenerierung.'; });
      default:
        break;
    }
  }

  // Called when user taps "Schlüssel gespeichert – weiter" on the showKey screen.
  void _onKeySaved() {
    setState(() => _step = _RecoveryStep.confirmKey);
  }

  // Called when user submits the correct key confirmation.
  // Bootstrap may still be running (cross-signing + key backup); wait for done.
  Future<void> _onKeyConfirmed() async {
    setState(() => _step = _RecoveryStep.applying);
    try {
      await _doneCompleter.future.timeout(const Duration(seconds: 90));
      if (mounted) setState(() => _step = _RecoveryStep.done);
    } catch (e) {
      if (mounted) setState(() { _step = _RecoveryStep.error; _error = 'Timeout: Bootstrap abgebrochen.'; });
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = widget.pt;
    final canClose = _step != _RecoveryStep.loading && _step != _RecoveryStep.applying && _step != _RecoveryStep.confirmKey;

    return Dialog(
      backgroundColor: pt.bg2,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(pt.rXl),
        side: BorderSide(color: pt.border),
      ),
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 440, minWidth: 320),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(20, 16, 12, 12),
              child: Row(
                children: [
                  Icon(Icons.key_rounded, size: 18, color: pt.accent),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      'Wiederherstellungsschlüssel',
                      style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600),
                    ),
                  ),
                  if (canClose)
                    IconButton(
                      icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16),
                      onPressed: () => Navigator.of(context).pop(_step == _RecoveryStep.done),
                      padding: EdgeInsets.zero,
                      constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28),
                    ),
                ],
              ),
            ),
            Divider(color: pt.border, height: 1),
            Padding(
              padding: const EdgeInsets.all(20),
              child: _buildBody(pt),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildBody(PyramidTheme pt) {
    return switch (_step) {
      _RecoveryStep.loading => const Center(
        child: Padding(padding: EdgeInsets.all(24), child: CircularProgressIndicator.adaptive()),
      ),
      _RecoveryStep.showKey => _ShowKeyBody(
        pt: pt,
        generatedKey: _generatedKey ?? '',
        copied: _copied,
        onCopy: () {
          Clipboard.setData(ClipboardData(text: _generatedKey ?? ''));
          setState(() => _copied = true);
        },
        onKeySaved: _onKeySaved,
      ),
      _RecoveryStep.confirmKey => _ConfirmKeyBody(
        pt: pt,
        expectedKey: _generatedKey ?? '',
        onConfirmed: _onKeyConfirmed,
      ),
      _RecoveryStep.applying => Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const CircularProgressIndicator.adaptive(),
          const SizedBox(height: 16),
          Text(
            'Schlüssel wird aktiviert…\nCross-Signing und Backup werden eingerichtet.',
            textAlign: TextAlign.center,
            style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5),
          ),
        ],
      ),
      _RecoveryStep.done => Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.check_circle_outline_rounded, color: PyramidColors.success, size: 52),
          const SizedBox(height: 12),
          Text(
            'Wiederherstellungsschlüssel wurde erfolgreich geändert.',
            textAlign: TextAlign.center,
            style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w500),
          ),
          const SizedBox(height: 6),
          Text(
            'Bewahre deinen Schlüssel sicher auf – du brauchst ihn bei Geräteverlust.',
            textAlign: TextAlign.center,
            style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.4),
          ),
          const SizedBox(height: 20),
          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: () => Navigator.of(context).pop(true),
              child: const Text('Fertig'),
            ),
          ),
        ],
      ),
      _RecoveryStep.error => Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.error_outline_rounded, color: PyramidColors.danger, size: 48),
          const SizedBox(height: 12),
          Text(
            _error ?? 'Ein unbekannter Fehler ist aufgetreten.',
            textAlign: TextAlign.center,
            style: TextStyle(color: pt.fgMuted, fontSize: 13),
          ),
          const SizedBox(height: 20),
          SizedBox(
            width: double.infinity,
            child: OutlinedButton(
              style: OutlinedButton.styleFrom(
                foregroundColor: pt.fg, side: BorderSide(color: pt.border),
                padding: const EdgeInsets.symmetric(vertical: 12),
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
              ),
              onPressed: () => Navigator.of(context).pop(false),
              child: const Text('Schließen'),
            ),
          ),
        ],
      ),
    };
  }
}

class _ShowKeyBody extends StatelessWidget {
  final PyramidTheme pt;
  final String generatedKey;
  final bool copied;
  final VoidCallback onCopy;
  final VoidCallback onKeySaved;

  const _ShowKeyBody({
    required this.pt,
    required this.generatedKey,
    required this.copied,
    required this.onCopy,
    required this.onKeySaved,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          'Dein neuer Wiederherstellungsschlüssel',
          style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600),
        ),
        const SizedBox(height: 8),
        Text(
          'Speichere diesen Schlüssel sicher – du brauchst ihn, wenn du den Zugang zu allen Geräten verlierst.',
          style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5),
        ),
        const SizedBox(height: 16),
        Container(
          decoration: BoxDecoration(
            color: pt.bg3,
            borderRadius: BorderRadius.circular(8),
            border: Border.all(color: pt.border),
          ),
          child: Row(
            children: [
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                  child: SelectableText(
                    generatedKey,
                    style: TextStyle(
                      color: pt.accent, fontSize: 13,
                      fontFamily: 'monospace', letterSpacing: 0.5, height: 1.6,
                    ),
                  ),
                ),
              ),
              IconButton(
                onPressed: onCopy,
                icon: Icon(
                  copied ? Icons.check_rounded : Icons.copy_rounded,
                  size: 18,
                  color: copied ? PyramidColors.success : pt.fgDim,
                ),
                tooltip: copied ? 'Kopiert!' : 'In Zwischenablage kopieren',
              ),
            ],
          ),
        ),
        const SizedBox(height: 12),
        Container(
          padding: const EdgeInsets.all(10),
          decoration: BoxDecoration(
            color: Colors.orange.withAlpha(28),
            borderRadius: BorderRadius.circular(8),
            border: Border.all(color: Colors.orange.withAlpha(80)),
          ),
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Icon(Icons.warning_amber_rounded, size: 16, color: Colors.orange.shade700),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  'Schreibe diesen Schlüssel auf oder speichere ihn in einem Passwort-Manager. Er kann nicht wiederhergestellt werden.',
                  style: TextStyle(color: Colors.orange.shade800, fontSize: 12, height: 1.4),
                ),
              ),
            ],
          ),
        ),
        const SizedBox(height: 20),
        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: onKeySaved,
            child: const Text('Schlüssel gespeichert – weiter'),
          ),
        ),
      ],
    );
  }
}

class _ConfirmKeyBody extends StatefulWidget {
  final PyramidTheme pt;
  final String expectedKey;
  final VoidCallback onConfirmed;

  const _ConfirmKeyBody({
    required this.pt,
    required this.expectedKey,
    required this.onConfirmed,
  });

  @override
  State<_ConfirmKeyBody> createState() => _ConfirmKeyBodyState();
}

class _ConfirmKeyBodyState extends State<_ConfirmKeyBody> {
  final _controller = TextEditingController();
  bool _mismatch = false;

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _submit() {
    final entered = _controller.text.trim();
    if (entered == widget.expectedKey) {
      widget.onConfirmed();
    } else {
      setState(() => _mismatch = true);
    }
  }

  @override
  Widget build(BuildContext context) {
    final pt = widget.pt;
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          'Schlüssel bestätigen',
          style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600),
        ),
        const SizedBox(height: 8),
        Text(
          'Gib deinen neuen Wiederherstellungsschlüssel zur Bestätigung ein.',
          style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5),
        ),
        const SizedBox(height: 16),
        TextField(
          controller: _controller,
          autofocus: true,
          style: TextStyle(
            color: pt.fg, fontSize: 13,
            fontFamily: 'monospace', letterSpacing: 0.4,
          ),
          decoration: InputDecoration(
            hintText: 'EsTX XXXX XXXX …',
            hintStyle: TextStyle(color: pt.fgDim, fontSize: 13),
            filled: true,
            fillColor: pt.bg3,
            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: _mismatch ? PyramidColors.danger : pt.border),
            ),
            focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(color: _mismatch ? PyramidColors.danger : pt.accent, width: 1.5),
            ),
            errorText: _mismatch ? 'Schlüssel stimmt nicht überein.' : null,
          ),
          onChanged: (_) { if (_mismatch) setState(() => _mismatch = false); },
          onSubmitted: (_) => _submit(),
        ),
        const SizedBox(height: 20),
        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: _submit,
            child: const Text('Aktivieren'),
          ),
        ),
      ],
    );
  }
}

