import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/file.dart';
import 'package:island/models/realm.dart';
import 'package:island/models/user.dart';

part 'chat.freezed.dart';
part 'chat.g.dart';

@freezed
abstract class SnChatRoom with _$SnChatRoom {
  const factory SnChatRoom({
    required String id,
    required String? name,
    required String? description,
    required int type,
    required bool isPublic,
    required String? pictureId,
    required SnCloudFile? picture,
    required String? backgroundId,
    required SnCloudFile? background,
    required String? realmId,
    required SnRealm? realm,
    required DateTime createdAt,
    required DateTime updatedAt,
    required DateTime? deletedAt,
    required List<SnChatMember>? members,
  }) = _SnChatRoom;

  factory SnChatRoom.fromJson(Map<String, dynamic> json) =>
      _$SnChatRoomFromJson(json);
}

@freezed
abstract class SnChatMessage with _$SnChatMessage {
  const factory SnChatMessage({
    required DateTime createdAt,
    required DateTime updatedAt,
    DateTime? deletedAt,
    required String id,
    String? content,
    String? nonce,
    @Default({}) Map<String, dynamic> meta,
    @Default([]) List<String> membersMetioned,
    DateTime? editedAt,
    @Default([]) List<SnCloudFile> attachments,
    @Default([]) List<SnChatReaction> reactions,
    String? repliedMessageId,
    String? forwardedMessageId,
    required String senderId,
    required SnChatMember sender,
    required String chatRoomId,
  }) = _SnChatMessage;

  factory SnChatMessage.fromJson(Map<String, dynamic> json) =>
      _$SnChatMessageFromJson(json);
}

@freezed
abstract class SnChatReaction with _$SnChatReaction {
  const factory SnChatReaction({
    required DateTime createdAt,
    required DateTime updatedAt,
    required DateTime? deletedAt,
    required String id,
    required String messageId,
    required String senderId,
    required SnChatMember sender,
    required String symbol,
    required int attitude,
  }) = _SnChatReaction;

  factory SnChatReaction.fromJson(Map<String, dynamic> json) =>
      _$SnChatReactionFromJson(json);
}

@freezed
abstract class SnChatMember with _$SnChatMember {
  const factory SnChatMember({
    required DateTime createdAt,
    required DateTime updatedAt,
    required DateTime? deletedAt,
    required String id,
    required String chatRoomId,
    required SnChatRoom? chatRoom,
    required String accountId,
    required SnAccount account,
    required String? nick,
    required int role,
    required int notify,
    required DateTime? joinedAt,
    required bool isBot,
  }) = _SnChatMember;

  factory SnChatMember.fromJson(Map<String, dynamic> json) =>
      _$SnChatMemberFromJson(json);
}

@freezed
abstract class SnChatSummary with _$SnChatSummary {
  const factory SnChatSummary({
    required int unreadCount,
    required SnChatMessage lastMessage,
  }) = _SnChatSummary;

  factory SnChatSummary.fromJson(Map<String, dynamic> json) =>
      _$SnChatSummaryFromJson(json);
}

class MessageChangeAction {
  static const String create = "create";
  static const String update = "update";
  static const String delete = "delete";
}

@freezed
abstract class MessageChange with _$MessageChange {
  const factory MessageChange({
    required String messageId,
    required String action,
    SnChatMessage? message,
    required DateTime timestamp,
  }) = _MessageChange;

  factory MessageChange.fromJson(Map<String, dynamic> json) =>
      _$MessageChangeFromJson(json);
}

@freezed
abstract class MessageSyncResponse with _$MessageSyncResponse {
  const factory MessageSyncResponse({
    @Default([]) List<MessageChange> changes,
    required DateTime currentTimestamp,
  }) = _MessageSyncResponse;

  factory MessageSyncResponse.fromJson(Map<String, dynamic> json) =>
      _$MessageSyncResponseFromJson(json);
}

@freezed
abstract class ChatRealtimeJoinResponse with _$ChatRealtimeJoinResponse {
  const factory ChatRealtimeJoinResponse({
    required String token,
    required Map<String, dynamic> config,
  }) = _ChatRealtimeJoinResponse;

  factory ChatRealtimeJoinResponse.fromJson(Map<String, dynamic> json) =>
      _$ChatRealtimeJoinResponseFromJson(json);
}
