import 'dart:convert';
import 'dart:math';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:real_estate_mobile/config/app_config.dart';

/// Twitter OAuth 2.0 PKCE flow for mobile.
class TwitterAuthService {
  static const _clientId = 'eWEzaDJ0al9lX1diOGY0ejRYeXM6MTpjaQ';
  static const _clientSecret = 'HadGMSRKKswfXOajbmggrnmLAn9cxJsl8GtFxGHqjX-CJ0A2Tu';
  static const _scope = 'tweet.read users.read offline.access';

  /// Derive redirect URI from API base URL (matches next-auth callback)
  static String get _redirectUri {
    final apiUrl = AppConfig.apiBaseUrl; // e.g. https://dev.re-quest.com/api/v1
    final base = apiUrl.replaceAll(RegExp(r'/api/v1/?$'), '');
    return '$base/api/auth/callback/twitter';
  }

  late final String _codeVerifier;
  late final String _codeChallenge;
  late final String _stateParam;

  TwitterAuthService() {
    _codeVerifier = _generateCodeVerifier();
    _codeChallenge = _generateCodeChallenge(_codeVerifier);
    _stateParam = _generateRandomString(32);
  }

  /// Build the Twitter authorization URL to open in a webview.
  String get authorizationUrl {
    final params = {
      'response_type': 'code',
      'client_id': _clientId,
      'redirect_uri': _redirectUri,
      'scope': _scope,
      'state': _stateParam,
      'code_challenge': _codeChallenge,
      'code_challenge_method': 'S256',
    };
    final query = params.entries
        .map((e) => '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
        .join('&');
    return 'https://twitter.com/i/oauth2/authorize?$query';
  }

  /// Check if a URL is the redirect callback and extract the auth code.
  String? extractCodeFromUrl(String url) {
    if (!url.startsWith(_redirectUri)) return null;
    final uri = Uri.parse(url);
    final state = uri.queryParameters['state'];
    if (state != _stateParam) return null;
    return uri.queryParameters['code'];
  }

  /// Exchange the auth code for tokens and fetch user info.
  Future<Map<String, dynamic>?> exchangeCodeForUser(String code) async {
    final dio = Dio();

    // Exchange code for access token (confidential client — Basic auth)
    final credentials = base64Encode(utf8.encode('$_clientId:$_clientSecret'));
    final tokenBody =
        'code=${Uri.encodeComponent(code)}'
        '&grant_type=authorization_code'
        '&redirect_uri=${Uri.encodeComponent(_redirectUri)}'
        '&code_verifier=${Uri.encodeComponent(_codeVerifier)}';

    final tokenResponse = await dio.post(
      'https://api.twitter.com/2/oauth2/token',
      options: Options(
        contentType: 'application/x-www-form-urlencoded',
        headers: {
          'Authorization': 'Basic $credentials',
        },
      ),
      data: tokenBody,
    );

    final accessToken = tokenResponse.data['access_token'] as String?;
    if (accessToken == null) return null;

    // Fetch user info
    final userResponse = await dio.get(
      'https://api.twitter.com/2/users/me',
      queryParameters: {'user.fields': 'id,name,username,profile_image_url'},
      options: Options(
        headers: {'Authorization': 'Bearer $accessToken'},
      ),
    );

    final userData = userResponse.data['data'] as Map<String, dynamic>?;
    if (userData == null) return null;

    return {
      'id': userData['id'],
      'name': userData['name'],
      'username': userData['username'],
      'avatar': userData['profile_image_url'],
    };
  }

  String _generateRandomString(int length) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
    final random = Random.secure();
    return List.generate(length, (_) => chars[random.nextInt(chars.length)]).join();
  }

  String _generateCodeVerifier() => _generateRandomString(64);

  String _generateCodeChallenge(String verifier) {
    final bytes = utf8.encode(verifier);
    final digest = sha256.convert(bytes);
    return base64Url.encode(digest.bytes).replaceAll('=', '');
  }
}
