/// Page d'Authentification UnionFlow
///
/// Interface utilisateur pour la connexion sécurisée via AppAuth (RFC 8252).
library keycloak_webview_auth_page;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_appauth/flutter_appauth.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:jwt_decoder/jwt_decoder.dart';
import '../../data/datasources/keycloak_auth_service.dart';
import '../../data/datasources/keycloak_role_mapper.dart';
import '../../data/models/user.dart';
import '../../../../shared/design_system/tokens/color_tokens.dart';
import '../../../../shared/design_system/tokens/spacing_tokens.dart';
import '../../../../shared/design_system/tokens/typography_tokens.dart';

/// Page d'authentification Keycloak via AppAuth
class KeycloakWebViewAuthPage extends StatefulWidget {
  final Function(User user) onAuthSuccess;
  final Function(String error) onAuthError;
  final VoidCallback? onAuthCancel;
  final int timeoutSeconds;

  const KeycloakWebViewAuthPage({
    super.key,
    required this.onAuthSuccess,
    required this.onAuthError,
    this.onAuthCancel,
    this.timeoutSeconds = 300,
  });

  @override
  State<KeycloakWebViewAuthPage> createState() => _KeycloakWebViewAuthPageState();
}

class _KeycloakWebViewAuthPageState extends State<KeycloakWebViewAuthPage> {
  bool _loading = true;
  String? _errorMessage;

  static const _appAuth = FlutterAppAuth();
  static const _storage = FlutterSecureStorage(
    aOptions: AndroidOptions(encryptedSharedPreferences: true),
    iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock_this_device),
  );

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

  Future<void> _authenticate() async {
    try {
      final result = await _appAuth.authorizeAndExchangeCode(
        AuthorizationTokenRequest(
          KeycloakConfig.clientId,
          'dev.lions.unionflow-mobile://auth/callback',
          serviceConfiguration: AuthorizationServiceConfiguration(
            authorizationEndpoint:
                '${KeycloakConfig.baseUrl}/realms/${KeycloakConfig.realm}/protocol/openid-connect/auth',
            tokenEndpoint: KeycloakConfig.tokenEndpoint,
          ),
          scopes: ['openid', 'profile', 'email', 'roles', 'offline_access'],
          additionalParameters: {'kc_locale': 'fr'},
          allowInsecureConnections: true,
        ),
      );

      if (result?.accessToken == null) {
        _onError('Authentification annulée ou échouée.');
        return;
      }

      await _storage.write(key: 'kc_access', value: result!.accessToken);
      if (result.refreshToken != null) {
        await _storage.write(key: 'kc_refresh', value: result.refreshToken);
      }
      if (result.idToken != null) {
        await _storage.write(key: 'kc_id', value: result.idToken);
      }

      final accessPayload = JwtDecoder.decode(result.accessToken!);
      final idPayload = result.idToken != null ? JwtDecoder.decode(result.idToken!) : accessPayload;

      final roles = _extractRoles(accessPayload);
      final primaryRole = KeycloakRoleMapper.mapToUserRole(roles);

      final user = User(
        id: idPayload['sub'] ?? '',
        email: idPayload['email'] ?? '',
        firstName: idPayload['given_name'] ?? '',
        lastName: idPayload['family_name'] ?? '',
        primaryRole: primaryRole,
        additionalPermissions: KeycloakRoleMapper.mapToPermissions(roles),
        isActive: true,
        lastLoginAt: DateTime.now(),
        createdAt: DateTime.now(),
      );

      if (mounted) {
        setState(() => _loading = false);
        Future.delayed(const Duration(milliseconds: 300), () {
          widget.onAuthSuccess(user);
        });
      }
    } catch (e) {
      _onError('Erreur d\'authentification: $e');
    }
  }

  void _onError(String error) {
    HapticFeedback.lightImpact();
    if (mounted) setState(() { _loading = false; _errorMessage = error; });
    widget.onAuthError(error);
  }

  void _handleCancel() {
    if (widget.onAuthCancel != null) {
      widget.onAuthCancel!();
    } else {
      Navigator.of(context).pop();
    }
  }

  List<String> _extractRoles(Map<String, dynamic> payload) {
    final roles = <String>[];
    if (payload['realm_access']?['roles'] != null) {
      roles.addAll((payload['realm_access']['roles'] as List).cast<String>());
    }
    if (payload['resource_access'] != null) {
      (payload['resource_access'] as Map).values.forEach((v) {
        if (v['roles'] != null) roles.addAll((v['roles'] as List).cast<String>());
      });
    }
    return roles.where((r) => !r.startsWith('default-roles-') && r != 'offline_access').toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: ColorTokens.surface,
      appBar: AppBar(
        backgroundColor: ColorTokens.primary,
        foregroundColor: ColorTokens.onPrimary,
        elevation: 0,
        title: Text(
          'Connexion Sécurisée',
          style: TypographyTokens.headlineSmall.copyWith(
            color: ColorTokens.onPrimary,
            fontWeight: FontWeight.w600,
          ),
        ),
        leading: IconButton(
          icon: const Icon(Icons.close),
          onPressed: _handleCancel,
          tooltip: 'Annuler',
        ),
      ),
      body: _errorMessage != null ? _buildErrorView() : _buildLoadingView(),
    );
  }

  Widget _buildLoadingView() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const CircularProgressIndicator(),
          const SizedBox(height: SpacingTokens.xl),
          Text(
            'Connexion en cours...',
            style: TypographyTokens.bodyLarge.copyWith(color: ColorTokens.onSurface),
          ),
        ],
      ),
    );
  }

  Widget _buildErrorView() {
    return Container(
      color: ColorTokens.surface,
      padding: const EdgeInsets.all(SpacingTokens.xxxl),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 80,
              height: 80,
              decoration: const BoxDecoration(
                color: ColorTokens.error,
                shape: BoxShape.circle,
              ),
              child: const Icon(Icons.error_outline, color: ColorTokens.onError, size: 48),
            ),
            const SizedBox(height: SpacingTokens.xxxl),
            Text(
              'Erreur de connexion',
              style: TypographyTokens.headlineSmall.copyWith(
                color: ColorTokens.onSurface,
                fontWeight: FontWeight.w600,
              ),
            ),
            const SizedBox(height: SpacingTokens.xl),
            Text(
              _errorMessage ?? 'Une erreur inattendue s\'est produite',
              textAlign: TextAlign.center,
              style: TypographyTokens.bodyMedium.copyWith(
                color: ColorTokens.onSurface.withOpacity(0.7),
              ),
            ),
            const SizedBox(height: SpacingTokens.huge),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton.icon(
                  onPressed: () {
                    setState(() { _loading = true; _errorMessage = null; });
                    _authenticate();
                  },
                  icon: const Icon(Icons.refresh),
                  label: const Text('Réessayer'),
                  style: ElevatedButton.styleFrom(
                    backgroundColor: ColorTokens.primary,
                    foregroundColor: ColorTokens.onPrimary,
                  ),
                ),
                OutlinedButton.icon(
                  onPressed: _handleCancel,
                  icon: const Icon(Icons.close),
                  label: const Text('Annuler'),
                  style: OutlinedButton.styleFrom(
                    foregroundColor: ColorTokens.onSurface,
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
