/// Modelo de datos de una emisora de radio.
///
/// Unifica los campos de la Radio Browser API con los de la tabla SQLite
/// de favoritos. Los campos opcionales pueden ser null cuando la emisora
/// no dispone de esa información.
class Emisora {
  final int? id;
  final String uuid;
  final String nombre;
  final String url;
  final String? favicon;
  final String? pais;
  final String? codigoPais; // ISO 3166-1 alpha-2
  final String? idioma;
  final String? tags;
  final String? codec;
  final int? bitrate;
  final int votes;
  final int clickcount;
  final int orden;

  const Emisora({
    this.id,
    required this.uuid,
    required this.nombre,
    required this.url,
    this.favicon,
    this.pais,
    this.codigoPais,
    this.idioma,
    this.tags,
    this.codec,
    this.bitrate,
    this.votes = 0,
    this.clickcount = 0,
    this.orden = 0,
  });

  /// Construye una [Emisora] desde la respuesta JSON de Radio Browser API.
  factory Emisora.fromApi(Map<String, dynamic> json) {
    return Emisora(
      uuid: json['stationuuid'] as String? ?? '',
      nombre: json['name'] as String? ?? 'Sin nombre',
      url: json['url_resolved'] as String? ?? json['url'] as String? ?? '',
      favicon: _nonEmpty(json['favicon'] as String?),
      pais: _nonEmpty(json['country'] as String?),
      codigoPais: _nonEmpty(json['countrycode'] as String?),
      idioma: _nonEmpty(json['language'] as String?),
      tags: _nonEmpty(json['tags'] as String?),
      codec: _nonEmpty(json['codec'] as String?),
      bitrate: json['bitrate'] as int?,
      votes: json['votes'] as int? ?? 0,
      clickcount: json['clickcount'] as int? ?? 0,
    );
  }

  /// Construye una [Emisora] desde una fila de la tabla `favoritos`.
  factory Emisora.fromMap(Map<String, dynamic> map) {
    return Emisora(
      id: map['id'] as int?,
      uuid: map['uuid'] as String,
      nombre: map['nombre'] as String,
      url: map['url'] as String,
      favicon: map['favicon'] as String?,
      pais: map['pais'] as String?,
      codigoPais: map['codigo_pais'] as String?,
      idioma: map['idioma'] as String?,
      tags: map['tags'] as String?,
      codec: map['codec'] as String?,
      bitrate: map['bitrate'] as int?,
      votes: map['votes'] as int? ?? 0,
      clickcount: map['clickcount'] as int? ?? 0,
      orden: map['orden'] as int? ?? 0,
    );
  }

  /// Serializa para inserción/actualización en SQLite.
  Map<String, dynamic> toMap() {
    return {
      'uuid': uuid,
      'nombre': nombre,
      'url': url,
      'favicon': favicon,
      'pais': pais,
      'codigo_pais': codigoPais,
      'idioma': idioma,
      'tags': tags,
      'codec': codec,
      'bitrate': bitrate,
      'votes': votes,
      'clickcount': clickcount,
      'orden': orden,
    };
  }

  Emisora copyWith({
    int? id,
    String? uuid,
    String? nombre,
    String? url,
    String? favicon,
    String? pais,
    String? codigoPais,
    String? idioma,
    String? tags,
    String? codec,
    int? bitrate,
    int? votes,
    int? clickcount,
    int? orden,
  }) {
    return Emisora(
      id: id ?? this.id,
      uuid: uuid ?? this.uuid,
      nombre: nombre ?? this.nombre,
      url: url ?? this.url,
      favicon: favicon ?? this.favicon,
      pais: pais ?? this.pais,
      codigoPais: codigoPais ?? this.codigoPais,
      idioma: idioma ?? this.idioma,
      tags: tags ?? this.tags,
      codec: codec ?? this.codec,
      bitrate: bitrate ?? this.bitrate,
      votes: votes ?? this.votes,
      clickcount: clickcount ?? this.clickcount,
      orden: orden ?? this.orden,
    );
  }

  /// Lista de géneros/tags como lista limpia.
  List<String> get generos {
    if (tags == null || tags!.isEmpty) return [];
    return tags!.split(',').map((t) => t.trim()).where((t) => t.isNotEmpty).toList();
  }

  static String? _nonEmpty(String? s) =>
      (s == null || s.trim().isEmpty) ? null : s.trim();

  @override
  String toString() => 'Emisora(uuid: $uuid, nombre: $nombre)';

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Emisora && runtimeType == other.runtimeType && uuid == other.uuid;

  @override
  int get hashCode => uuid.hashCode;
}
