// Version: 1.0.0 | Created: 2026-04-11
// Dialog for entering a recovery key to restore encrypted message keys
// from the server-side key backup (SSSS / Secure Secret Storage).

import 'package:flutter/material.dart';
import 'package:matrix/encryption/ssss.dart';
import 'package:matrix/matrix.dart';

/// Shows a dialog that asks the user for their recovery key, unlocks SSSS,
/// and restores all Megolm session keys from the server backup.
///
/// Returns `true` if keys were restored successfully, `false` otherwise.
Future<bool> showKeyRestoreDialog(BuildContext context, Client client) async {
  final result = await showDialog<bool>(
    context: context,
    barrierDismissible: false,
    builder: (_) => _KeyRestoreDialog(client: client),
  );
  return result ?? false;
}

class _KeyRestoreDialog extends StatefulWidget {
  const _KeyRestoreDialog({required this.client});
  final Client client;

  @override
  State<_KeyRestoreDialog> createState() => _KeyRestoreDialogState();
}

enum _RestorePhase { input, unlocking, downloading, done, error }

class _KeyRestoreDialogState extends State<_KeyRestoreDialog> {
  final _controller = TextEditingController();
  _RestorePhase _phase = _RestorePhase.input;
  String? _error;

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

  Future<void> _restore() async {
    final key = _controller.text.trim();
    if (key.isEmpty) return;

    final enc = widget.client.encryption;
    if (enc == null) {
      setState(() {
        _phase = _RestorePhase.error;
        _error = 'Encryption is not available.';
      });
      return;
    }

    // Phase 1: Unlock SSSS with the recovery key
    setState(() => _phase = _RestorePhase.unlocking);
    try {
      final ssssKey = enc.ssss.open();
      await ssssKey.unlock(keyOrPassphrase: key);
      debugPrint('[KeyRestore] SSSS unlocked successfully');
    } on InvalidPassphraseException {
      setState(() {
        _phase = _RestorePhase.error;
        _error = 'Invalid recovery key. Please check and try again.';
      });
      return;
    } on Exception catch (e) {
      setState(() {
        _phase = _RestorePhase.error;
        _error = 'Could not unlock: ${e.toString().split('\n').first}';
      });
      return;
    }

    // Phase 2: Download and decrypt all keys from backup
    setState(() => _phase = _RestorePhase.downloading);
    try {
      await enc.keyManager.loadAllKeys();
      debugPrint('[KeyRestore] All keys loaded from backup');
      setState(() => _phase = _RestorePhase.done);
    } on MatrixException catch (e) {
      if (e.errcode == 'M_NOT_FOUND') {
        setState(() {
          _phase = _RestorePhase.error;
          _error = 'No key backup found on the server for this account.';
        });
      } else {
        setState(() {
          _phase = _RestorePhase.error;
          _error = 'Server error: ${e.errorMessage}';
        });
      }
    } on Exception catch (e) {
      setState(() {
        _phase = _RestorePhase.error;
        _error = 'Failed to download keys: ${e.toString().split('\n').first}';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text(switch (_phase) {
        _RestorePhase.input => 'Restore Message Keys',
        _RestorePhase.unlocking => 'Unlocking...',
        _RestorePhase.downloading => 'Downloading Keys...',
        _RestorePhase.done => 'Keys Restored',
        _RestorePhase.error => 'Restore Failed',
      }),
      content: switch (_phase) {
        _RestorePhase.input => Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text(
                'Enter your recovery key to decrypt old messages. '
                'This is the key you were given when you set up '
                'encryption in Element.',
              ),
              const SizedBox(height: 16),
              TextField(
                controller: _controller,
                decoration: const InputDecoration(
                  hintText: 'EsTc oRgW rqHN...',
                  labelText: 'Recovery key',
                  border: OutlineInputBorder(),
                ),
                maxLines: 3,
                textInputAction: TextInputAction.done,
                onSubmitted: (_) => _restore(),
              ),
            ],
          ),
        _RestorePhase.unlocking => const _ProgressContent(
            message: 'Verifying recovery key...',
          ),
        _RestorePhase.downloading => const _ProgressContent(
            message: 'Downloading and decrypting message keys...\n'
                'This may take a moment.',
          ),
        _RestorePhase.done => const Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.check_circle, color: Colors.green, size: 48),
              SizedBox(height: 16),
              Text(
                'Message keys have been restored. '
                'Go back to your rooms — previously encrypted '
                'messages should now be readable.',
              ),
            ],
          ),
        _RestorePhase.error => Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Icon(Icons.error_outline, color: Colors.red, size: 48),
              const SizedBox(height: 16),
              Text(_error ?? 'An unknown error occurred.'),
            ],
          ),
      },
      actions: switch (_phase) {
        _RestorePhase.input => [
            TextButton(
              onPressed: () => Navigator.of(context).pop(false),
              child: const Text('Cancel'),
            ),
            ElevatedButton(
              onPressed: _restore,
              child: const Text('Restore'),
            ),
          ],
        _RestorePhase.unlocking || _RestorePhase.downloading => [],
        _RestorePhase.done => [
            ElevatedButton(
              onPressed: () => Navigator.of(context).pop(true),
              child: const Text('Done'),
            ),
          ],
        _RestorePhase.error => [
            TextButton(
              onPressed: () =>
                  setState(() => _phase = _RestorePhase.input),
              child: const Text('Try again'),
            ),
            TextButton(
              onPressed: () => Navigator.of(context).pop(false),
              child: const Text('Close'),
            ),
          ],
      },
    );
  }
}

class _ProgressContent extends StatelessWidget {
  const _ProgressContent({required this.message});
  final String message;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const CircularProgressIndicator(),
        const SizedBox(height: 16),
        Text(message, textAlign: TextAlign.center),
      ],
    );
  }
}
