import 'package:comwell_key_app/utils/json.dart';
import 'package:json_annotation/json_annotation.dart';

part '../../.generated/hotel_information/models/structured_text.g.dart';

sealed class StructuredTextBlock {
  factory StructuredTextBlock.fromJson(Json json) {
    switch (json['type'] as String) {
      case 'HeaderStructuredTextModel':
        return HeaderStructuredTextModel.fromJson(json);
      case 'TextModelStructuredTextModel':
        return TextModelStructuredTextModel.fromJson(json);
      case 'AddressStructuredTextModel':
        return AddressStructuredTextModel.fromJson(json);
      case 'EmailContactStructuredTextModel':
        return EmailContactStructuredTextModel.fromJson(json);
      case 'PhoneContactStructuredTextModel':
        return PhoneContactStructuredTextModel.fromJson(json);
      case 'ImageWidgetStructuredTextModel':
        return ImageWidgetStructuredTextModel.fromJson(json);
      case 'SpaBookingLinkStructuredTextModel':
        return SpaBookingLinkStructuredTextModel.fromJson(json);
      case 'HotelInformationListTileStructuredTextModel':
        return HotelInformationListTileStructuredTextModel.fromJson(json);
      case 'MapsBottomModalStructuredTextModel':
        return MapsBottomModalStructuredTextModel.fromJson(json);
      case 'OpeningHoursStructuredTextModel':
        return OpeningHoursStructuredTextModel.fromJson(json);
      case 'PageTitleStructuredTextModel':
        return PageTitleStructuredTextModel.fromJson(json);
      case 'PracticalInformationStructuredTextModel':
        return PracticalInformationStructuredTextModel.fromJson(json);
      case 'EmailStructuredTextModel':
        return EmailStructuredTextModel.fromJson(json);
      default:
        throw Exception('Unknown StructuredTextBlock type: \'${json['type']}\'');
    }
  }
  Json toJson();
}

@JsonSerializable()
class HeaderStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String header;

  HeaderStructuredTextModel({
    this.type = 'HeaderStructuredTextModel',
    required this.header,
  });

  factory HeaderStructuredTextModel.fromJson(Json json) => _$HeaderStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$HeaderStructuredTextModelToJson(this);

  @override
  String toString() {
    return header;
  }
}

@JsonSerializable()
class TextModelStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String text;

  TextModelStructuredTextModel({
    this.type = 'TextModelStructuredTextModel',
    required this.text,
  });

  factory TextModelStructuredTextModel.fromJson(Json json) => _$TextModelStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$TextModelStructuredTextModelToJson(this);

  @override
  String toString() {
    return text;
  }
}

@JsonSerializable()
class AddressStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String headline;
  final String address;

  AddressStructuredTextModel({
    this.type = 'AddressStructuredTextModel',
    required this.headline,
    required this.address,
  });

  factory AddressStructuredTextModel.fromJson(Json json) => _$AddressStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$AddressStructuredTextModelToJson(this);

  @override
  String toString() {
    return "$headline\n$address";
  }
}

@JsonSerializable()
class EmailContactStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String headline;
  final String email;

  EmailContactStructuredTextModel({
    this.type = 'EmailContactStructuredTextModel',
    required this.headline,
    required this.email,
  });

  factory EmailContactStructuredTextModel.fromJson(Json json) => _$EmailContactStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$EmailContactStructuredTextModelToJson(this);

  @override
  String toString() {
    return "$headline\n$email";
  }
}

@JsonSerializable()
class PhoneContactStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String headline;
  final String phoneNumber;

  PhoneContactStructuredTextModel({
    this.type = 'PhoneContactStructuredTextModel',
    required this.headline,
    required this.phoneNumber,
  });

  factory PhoneContactStructuredTextModel.fromJson(Json json) => _$PhoneContactStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$PhoneContactStructuredTextModelToJson(this);

  @override
  String toString() {
    return "$headline\n$phoneNumber";
  }
}

@JsonSerializable()
class ImageWidgetStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String image;

  ImageWidgetStructuredTextModel({
    this.type = 'ImageWidgetStructuredTextModel',
    required this.image,
  });

  factory ImageWidgetStructuredTextModel.fromJson(Json json) => _$ImageWidgetStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$ImageWidgetStructuredTextModelToJson(this);

  @override
  String toString() => image;
}

@JsonSerializable()
class SpaBookingLinkStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String link;

  SpaBookingLinkStructuredTextModel({
    this.type = 'SpaBookingLinkStructuredTextModel',
    required this.link,
  });

  factory SpaBookingLinkStructuredTextModel.fromJson(Json json) => _$SpaBookingLinkStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$SpaBookingLinkStructuredTextModelToJson(this);

  @override
  String toString() => link;
}

@JsonSerializable()
class HotelInformationListTileStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String iconPath;
  final String title;

  HotelInformationListTileStructuredTextModel({
    this.type = 'HotelInformationListTileStructuredTextModel',
    required this.iconPath,
    required this.title,
  });

  factory HotelInformationListTileStructuredTextModel.fromJson(Json json) => _$HotelInformationListTileStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$HotelInformationListTileStructuredTextModelToJson(this);

  @override
  String toString() => title;
}

@JsonSerializable()
class MapsBottomModalStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String address;

  MapsBottomModalStructuredTextModel({
    this.type = 'MapsBottomModalStructuredTextModel',
    required this.address,
  });

  factory MapsBottomModalStructuredTextModel.fromJson(Json json) => _$MapsBottomModalStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$MapsBottomModalStructuredTextModelToJson(this);

  @override
  String toString() => address;
}

@JsonSerializable()
class OpeningHoursStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String openingHours;

  OpeningHoursStructuredTextModel({
    this.type = 'OpeningHoursStructuredTextModel',
    required this.openingHours,
  });

  factory OpeningHoursStructuredTextModel.fromJson(Json json) => _$OpeningHoursStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$OpeningHoursStructuredTextModelToJson(this);

  @override
  String toString() => openingHours;
}

@JsonSerializable()
class PageTitleStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String title;

  PageTitleStructuredTextModel({
    this.type = 'PageTitleStructuredTextModel',
    required this.title,
  });

  factory PageTitleStructuredTextModel.fromJson(Json json) => _$PageTitleStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$PageTitleStructuredTextModelToJson(this);

  @override
  String toString() => title;
}

@JsonSerializable()
class PracticalInformationStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String restaurantId;

  PracticalInformationStructuredTextModel({
    this.type = 'PracticalInformationStructuredTextModel',
    required this.restaurantId,
  });

  factory PracticalInformationStructuredTextModel.fromJson(Json json) => _$PracticalInformationStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$PracticalInformationStructuredTextModelToJson(this);

  @override
  String toString() => restaurantId;
}

@JsonSerializable()
class EmailStructuredTextModel implements StructuredTextBlock {
  @JsonKey(name: 'type')
  final String type;
  final String email;

  EmailStructuredTextModel({
    this.type = 'EmailStructuredTextModel',
    required this.email,
  });

  factory EmailStructuredTextModel.fromJson(Json json) => _$EmailStructuredTextModelFromJson(json);
  @override
  Json toJson() => _$EmailStructuredTextModelToJson(this);

  @override
  String toString() => email;
}