// Version: 2.0.0 | Created: 2026-04-01 | Updated: 2026-04-11
// Auth repository: handles all Matrix login/logout API interactions.
// Uses the Matrix Dart SDK — no raw HTTP calls for auth.

import 'package:flutter/foundation.dart';
import 'package:matrix/matrix.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../../core/config/app_config.dart';
import '../../../core/network/matrix_client.dart';
import '../domain/auth_failure.dart';

part 'auth_repository.g.dart';

@Riverpod(keepAlive: true)
AuthRepository authRepository(Ref ref) {
  return AuthRepository(client: ref.watch(matrixClientProvider));
}

/// Handles authentication interactions with the Matrix homeserver.
class AuthRepository {
  AuthRepository({required Client client}) : _client = client;

  final Client _client;

  /// Attempts password login. Returns [LoginResponse] on success,
  /// throws [AuthFailure] on failure.
  ///
  /// Matrix error codes mapped:
  ///   M_FORBIDDEN → [InvalidCredentials]
  ///   M_USER_DEACTIVATED → [AccountDisabled]
  ///   Network error → [NetworkError]
  Future<LoginResponse> login({
    required String username,
    required String password,
  }) async {
    try {
      _client.homeserver = Uri.parse(AppConfig.matrixBaseUrl);
      final response = await _client.login(
        LoginType.mLoginPassword,
        identifier: AuthenticationUserIdentifier(user: username),
        password: password,
        initialDeviceDisplayName: AppConfig.appName,
      );
      debugPrint('[M8Chat] Login complete. encryptionEnabled=${_client.encryptionEnabled}');
      debugPrint('[M8Chat] encryption=${_client.encryption}');
      return response;
    } on MatrixException catch (e) {
      throw switch (e.errcode) {
        'M_FORBIDDEN' => const AuthFailure.invalidCredentials(),
        'M_USER_DEACTIVATED' => const AuthFailure.accountDisabled(),
        _ => AuthFailure.serverError(
          statusCode: e.response?.statusCode,
          message: e.errorMessage,
        ),
      };
    } on Exception catch (e) {
      // Covers SocketException, TimeoutException, etc.
      final msg = e.toString().toLowerCase();
      if (msg.contains('socket') ||
          msg.contains('connection') ||
          msg.contains('host lookup') ||
          msg.contains('timeout')) {
        throw AuthFailure.networkError(message: e.toString());
      }
      throw AuthFailure.unknown(message: e.toString());
    }
  }

  /// Logs out the current session on the homeserver.
  /// Silently succeeds if the token is already invalid (network-first logout).
  Future<void> logout() async {
    try {
      await _client.logout();
    } on MatrixException {
      // Token already invalid — treat as successful logout.
    } on Exception {
      // Network offline — proceed with local cleanup regardless.
    }
  }

  // restoreSession() removed — web app requires fresh login every visit.
}
