import 'package:dio/dio.dart';

import 'auth_token_provider.dart';

/// **Nur für Phase A / Smoke-Tests.** Spricht direkt den Keycloak-
/// Token-Endpoint mit `grant_type=password` an — bequem für
/// Dev-Setups, in Produktion komplett ungeeignet (kein PKCE, keine
/// Userinteraktion, Credentials in der App).
///
/// In Phase B ersetzt diese Klasse die KeycloakOidcTokenProvider-
/// Implementierung, die auf flutter_appauth basiert.
///
/// Cached den Token im Speicher und erneuert ihn, sobald die
/// Restlaufzeit unter 30 s fällt — kein eingebauter Refresh-Token-
/// Flow, dafür einfach.
class DevPasswordGrantTokenProvider implements AuthTokenProvider {
  DevPasswordGrantTokenProvider({
    required this.tokenEndpoint,
    required this.clientId,
    required this.username,
    required this.password,
    Dio? dio,
  }) : _dio = dio ?? Dio();

  final Dio _dio;
  final String tokenEndpoint;
  final String clientId;
  final String username;
  final String password;

  String? _cachedToken;
  DateTime? _expiresAt;

  @override
  Future<String?> currentAccessToken() async {
    final now = DateTime.now();
    final cached = _cachedToken;
    final expiresAt = _expiresAt;
    if (cached != null &&
        expiresAt != null &&
        expiresAt.isAfter(now.add(const Duration(seconds: 30)))) {
      return cached;
    }

    final response = await _dio.post<Map<String, dynamic>>(
      tokenEndpoint,
      data: {
        'grant_type': 'password',
        'client_id': clientId,
        'username': username,
        'password': password,
        'scope': 'openid',
      },
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );

    final data = response.data;
    if (data == null) {
      throw StateError('Keycloak token endpoint lieferte leeren Body');
    }
    final token = data['access_token'] as String?;
    final expiresIn = data['expires_in'] as int?;
    if (token == null || expiresIn == null) {
      throw StateError(
        'Keycloak token endpoint lieferte unerwartete Antwort: $data',
      );
    }

    _cachedToken = token;
    _expiresAt = now.add(Duration(seconds: expiresIn));
    return token;
  }
}
