import 'package:json_annotation/json_annotation.dart';

part 'room.g.dart';

@JsonSerializable()
class CreateRoomRequest {
  final bool success;
  CreateRoomRequest({required this.success});
  factory CreateRoomRequest.fromJson(Map<String, dynamic> json) => _$CreateRoomRequestFromJson(json);

  Map<String, dynamic> toJson() => _$CreateRoomRequestToJson(this);
}

@JsonSerializable()
class CreateRoomResponse {
  final bool success;
  final String? roomCode;
  final String? error;

  CreateRoomResponse({required this.success, required this.roomCode, this.error});

  factory CreateRoomResponse.fromJson(Map<String, dynamic> json) => _$CreateRoomResponseFromJson(json);

  Map<String, dynamic> toJson() => _$CreateRoomResponseToJson(this);
}

sealed class GameRoomMessage {
  GameRoomMessage(this.roomUuid);
  final String roomUuid;
  abstract final String type;

  factory GameRoomMessage.fromJson(Map<String, dynamic> json) {
    return switch (json['type']) {
      'ping' => PingMessage.fromJson(json),
      'roomPing' => RoomPingMessage.fromJson(json),
      'playerVote' => PlayerVoteMessage.fromJson(json),
      _ => throw Exception('Unknown message type'),
    };
  }

  Map<String, dynamic> toJson();
}

enum PingDestination { client, server }

@JsonSerializable()
class PingMessage extends GameRoomMessage {
  DateTime timestamp;
  final PingDestination dest;
  final String userUuid;

  PingMessage(super.roomUuid, {required this.dest, required this.userUuid}) {
    timestamp = DateTime.now();
    type = 'ping';
  }

  factory PingMessage.fromJson(Map<String, dynamic> json) => _$PingMessageFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$PingMessageToJson(this);

  @override
  late final String type;
}

@JsonSerializable()
class RoomPingMessage extends GameRoomMessage {
  late final DateTime timestamp;
  final PingDestination dest;

  RoomPingMessage(super.roomUuid, {required this.dest}) {
    timestamp = DateTime.now();
    type = 'roomPing';
  }

  factory RoomPingMessage.fromJson(Map<String, dynamic> json) => _$RoomPingMessageFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$RoomPingMessageToJson(this);

  @override
  late final String type;
}

@JsonSerializable()
class PlayerVoteMessage extends GameRoomMessage {
  final String playerUuid;
  final int vote;

  PlayerVoteMessage(super.roomUuid, {required this.playerUuid, required this.vote}) {
    type = 'playerVote';
  }

  factory PlayerVoteMessage.fromJson(Map<String, dynamic> json) => _$PlayerVoteMessageFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$PlayerVoteMessageToJson(this);

  @override
  late final String type;
}