/// Implémentation du repository de messagerie
library messaging_repository_impl;

import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../../core/error/exceptions.dart';
import '../../../../core/error/failures.dart';
import '../../../../core/network/network_info.dart';
import '../../domain/entities/conversation.dart';
import '../../domain/entities/message.dart';
import '../../domain/entities/message_template.dart';
import '../../domain/repositories/messaging_repository.dart';
import '../datasources/messaging_remote_datasource.dart';

@LazySingleton(as: MessagingRepository)
class MessagingRepositoryImpl implements MessagingRepository {
  final MessagingRemoteDatasource remoteDatasource;
  final NetworkInfo networkInfo;

  MessagingRepositoryImpl({
    required this.remoteDatasource,
    required this.networkInfo,
  });

  @override
  Future<Either<Failure, List<Conversation>>> getConversations({
    String? organizationId,
    bool includeArchived = false,
  }) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      final conversations = await remoteDatasource.getConversations(
        organizationId: organizationId,
        includeArchived: includeArchived,
      );
      return Right(conversations);
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  @override
  Future<Either<Failure, Conversation>> getConversationById(
      String conversationId) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      final conversation =
          await remoteDatasource.getConversationById(conversationId);
      return Right(conversation);
    } on NotFoundException {
      return Left(NotFoundFailure('Conversation non trouvée'));
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  @override
  Future<Either<Failure, Conversation>> createConversation({
    required String name,
    required List<String> participantIds,
    String? organizationId,
    String? description,
  }) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      final conversation = await remoteDatasource.createConversation(
        name: name,
        participantIds: participantIds,
        organizationId: organizationId,
        description: description,
      );
      return Right(conversation);
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  @override
  Future<Either<Failure, List<Message>>> getMessages({
    required String conversationId,
    int? limit,
    String? beforeMessageId,
  }) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      final messages = await remoteDatasource.getMessages(
        conversationId: conversationId,
        limit: limit,
        beforeMessageId: beforeMessageId,
      );
      return Right(messages);
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  @override
  Future<Either<Failure, Message>> sendMessage({
    required String conversationId,
    required String content,
    List<String>? attachments,
    MessagePriority priority = MessagePriority.normal,
  }) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      final message = await remoteDatasource.sendMessage(
        conversationId: conversationId,
        content: content,
        attachments: attachments,
        priority: priority,
      );
      return Right(message);
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  @override
  Future<Either<Failure, Message>> sendBroadcast({
    required String organizationId,
    required String subject,
    required String content,
    MessagePriority priority = MessagePriority.normal,
    List<String>? attachments,
  }) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      final message = await remoteDatasource.sendBroadcast(
        organizationId: organizationId,
        subject: subject,
        content: content,
        priority: priority,
        attachments: attachments,
      );
      return Right(message);
    } on ForbiddenException catch (e) {
      return Left(ForbiddenFailure(e.message));
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  @override
  Future<Either<Failure, void>> markMessageAsRead(String messageId) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      await remoteDatasource.markMessageAsRead(messageId);
      return const Right(null);
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  @override
  Future<Either<Failure, int>> getUnreadCount({String? organizationId}) async {
    if (!await networkInfo.isConnected) {
      return Left(NetworkFailure('Pas de connexion Internet'));
    }

    try {
      final count =
          await remoteDatasource.getUnreadCount(organizationId: organizationId);
      return Right(count);
    } on UnauthorizedException {
      return Left(UnauthorizedFailure('Session expirée'));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } catch (e) {
      return Left(UnexpectedFailure('Erreur inattendue: $e'));
    }
  }

  // === MÉTHODES NON IMPLÉMENTÉES (Stubs pour compilation) ===
  // À implémenter selon besoins backend

  @override
  Future<Either<Failure, void>> archiveConversation(String conversationId) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, Message>> sendTargetedMessage({
    required String organizationId,
    required List<String> targetRoles,
    required String subject,
    required String content,
    MessagePriority priority = MessagePriority.normal,
  }) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, void>> markConversationAsRead(String conversationId) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, void>> toggleMuteConversation(String conversationId) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, void>> togglePinConversation(String conversationId) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, Message>> editMessage({
    required String messageId,
    required String newContent,
  }) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, void>> deleteMessage(String messageId) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, List<MessageTemplate>>> getTemplates({
    String? organizationId,
    TemplateCategory? category,
  }) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, MessageTemplate>> getTemplateById(String templateId) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, MessageTemplate>> createTemplate({
    required String name,
    required String description,
    required TemplateCategory category,
    required String subject,
    required String body,
    List<Map<String, dynamic>>? variables,
    String? organizationId,
  }) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, MessageTemplate>> updateTemplate({
    required String templateId,
    String? name,
    String? description,
    String? subject,
    String? body,
    bool? isActive,
  }) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, void>> deleteTemplate(String templateId) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, Message>> sendFromTemplate({
    required String templateId,
    required Map<String, String> variables,
    required List<String> recipientIds,
  }) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }

  @override
  Future<Either<Failure, Map<String, dynamic>>> getMessagingStats({
    required String organizationId,
    DateTime? startDate,
    DateTime? endDate,
  }) async {
    return Left(NotImplementedFailure('Fonctionnalité en cours de développement'));
  }
}
